{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "对应 `tf.keras` 的01~02章节"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T04:58:46.125519Z",
     "start_time": "2025-03-27T04:58:30.077026Z"
    }
   },
   "source": [
    "import matplotlib as mpl\n",
    "import matplotlib.pyplot as plt\n",
    "%matplotlib inline\n",
    "import numpy as np\n",
    "import sklearn\n",
    "import pandas as pd\n",
    "import os\n",
    "import sys\n",
    "import time\n",
    "from tqdm.auto import tqdm\n",
    "import torch\n",
    "import torch.nn as nn\n",
    "import torch.nn.functional as F\n",
    "\n",
    "print(sys.version_info)\n",
    "for module in mpl, np, pd, sklearn, torch:\n",
    "    print(module.__name__, module.__version__)\n",
    "    \n",
    "device = torch.device(\"cuda:0\") if torch.cuda.is_available() else torch.device(\"cpu\")\n",
    "print(device)\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "sys.version_info(major=3, minor=12, micro=3, releaselevel='final', serial=0)\n",
      "matplotlib 3.10.1\n",
      "numpy 2.2.3\n",
      "pandas 2.2.3\n",
      "sklearn 1.6.1\n",
      "torch 2.6.0+cu118\n",
      "cuda:0\n"
     ]
    }
   ],
   "execution_count": 1
  },
  {
   "cell_type": "code",
   "source": [
    "28*28"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T04:59:04.622847Z",
     "start_time": "2025-03-27T04:59:04.611317Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "784"
      ]
     },
     "execution_count": 2,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 2
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "## 数据准备1，为了看灰度图片"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:15.248649Z",
     "start_time": "2025-03-27T08:07:11.587695Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torchvision import transforms\n",
    "\n",
    "\n",
    "# 定义数据集的变换\n",
    "transform = transforms.Compose([\n",
    "])\n",
    "# fashion_mnist图像分类数据集，衣服分类，60000张训练图片，10000张测试图片\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 当然也可以用 torch.utils.data.Dataset 实现人为划分"
   ],
   "outputs": [],
   "execution_count": 3
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:28.461615Z",
     "start_time": "2025-03-27T08:07:28.452860Z"
    }
   },
   "cell_type": "code",
   "source": "type(train_ds)",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torchvision.datasets.mnist.FashionMNIST"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 4
  },
  {
   "cell_type": "code",
   "source": [
    "len(train_ds)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:34.165539Z",
     "start_time": "2025-03-27T08:07:34.156888Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "60000"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 5
  },
  {
   "cell_type": "code",
   "source": [
    "type(train_ds[0])"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:37.276980Z",
     "start_time": "2025-03-27T08:07:37.262239Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "tuple"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 6
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:46.970065Z",
     "start_time": "2025-03-27T08:07:46.963698Z"
    }
   },
   "source": [
    "# 通过id取数据，取到的是一个元祖,是第一个样本,在训练时，把特征和标签分开\n",
    "img, label = train_ds[0]"
   ],
   "outputs": [],
   "execution_count": 7
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:07:57.027220Z",
     "start_time": "2025-03-27T08:07:57.017739Z"
    }
   },
   "cell_type": "code",
   "source": "type(img) #tensor中文是 张量,和numpy的ndarray类似",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PIL.Image.Image"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 8
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:08:02.747254Z",
     "start_time": "2025-03-27T08:08:02.699473Z"
    }
   },
   "cell_type": "code",
   "source": "img",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<PIL.Image.Image image mode=L size=28x28>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAABwAAAAcCAAAAABXZoBIAAACS0lEQVR4AWKgA2BkYOD1ZGBgZAHZxcjIAKZBbBBm+quS8v3rj1N/GBiZGP8wMKNIMv91cnnCzuU65+X/vww8/76hSP5iMFVgZtpp2HXm8nUz02PHGUHGQTHjf9cugd//GE7f+cUo8ft0yDSEJCMDw/8TCgyMf34x/Ph3/vYfT0VphLH/GRgY3kt+Z2fl+cH5z8aSSWwHqmsZuJiZvn18p/CPkYnr7z9ZBiaofQwMjMwMPFI/frH++sr/j537K9sldhOE5H9mhnBJJg4Gbtlf7L//cQhvusaCkGT5xXDlBxsXl6rSD2Yunr9PoraeYAGZx8T4+x/DHwaGbV+/s/1/zczxm+H3P2a9jwxMDMz///z6+Y+BwW7ime9v//z78/XrXw6GbwxsX4NAYc3AICSlJhmk/oPpN+czVjbhX1zHeOz+fWR9qcnIYNkkKvCX+cMfrl+M36+HneEVVGC4x/v5GycPHxcj83GpP3+/MTB/Z2DgF0lwy3z24/49VeFfrLxsf+UBY0xqv8vDw87Ayv/4mSiTRACHIrexMdMvJjYGRlYLlpeP+X485mHje/eQ5/uPP+svKwj9+vD77y/Wf4xsaixP/z/mFvnw5jULOysHL9Mbza+P37O/+f3nN6fERwOWC+sTn937wcPGwcb88+//by/+/WX5wfPrw4fffxRfMjIweBWLv/7wl5mNhZnxPysrGysjA+NLBrZ/EpfCGJn+MTA4tYnxMzGz/GV8+f/pvy/MDP9/f2Paff0YJBAYGBg0RN/LPPx1Fx5HFDIAaCTYdiCc4RIAAAAASUVORK5CYII=",
      "image/jpeg": "/9j/4AAQSkZJRgABAQAAAQABAAD/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRofHh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/wAALCAAcABwBAREA/8QAHwAAAQUBAQEBAQEAAAAAAAAAAAECAwQFBgcICQoL/8QAtRAAAgEDAwIEAwUFBAQAAAF9AQIDAAQRBRIhMUEGE1FhByJxFDKBkaEII0KxwRVS0fAkM2JyggkKFhcYGRolJicoKSo0NTY3ODk6Q0RFRkdISUpTVFVWV1hZWmNkZWZnaGlqc3R1dnd4eXqDhIWGh4iJipKTlJWWl5iZmqKjpKWmp6ipqrKztLW2t7i5usLDxMXGx8jJytLT1NXW19jZ2uHi4+Tl5ufo6erx8vP09fb3+Pn6/9oACAEBAAA/APn+tbw1oNx4m8QWmkWx2yXD4LkZCADJJ+gFbviL4a63oc7COE3MW4hdn38duD976jNc9daDqllIsc9lKrMu4YGeMkdR7gj8KzcV7H8BtEvV16+1iWCeG1Wz8mOV02pIzupwCeuAp6Z98cZ90aIzLIlw0c0ZJ4KgjHoeOa+evjS9n/wnMcNxBPCYLKONFhA2FNzMpGenDcgd816V4K03wefC+m3NlpVhP+5QSXBiR5fMx825iMg5zwce3FdbOzTwgW90lu6uCm8eYrL02soIyCPQgggEdMGQ3cluiPNK0rJwrRQBNueuMkt+teNfGKxsdY8WWdxNqcNo66eieXMwVsb5DnH415Hp2rajpE5n02/urOUjBe3laMkehIPIrVm8eeLrhNknibVivoLtx/I1UPinxC3XXtUP1vJP8ay5JZJpGkldnduSzHJP41//2Q=="
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 9
  },
  {
   "cell_type": "code",
   "source": [
    "type(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:08:06.269113Z",
     "start_time": "2025-03-27T08:08:06.260130Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "PIL.Image.Image"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 10
  },
  {
   "cell_type": "code",
   "source": [
    "label"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:08:11.742030Z",
     "start_time": "2025-03-27T08:08:11.730677Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "9"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 11
  },
  {
   "cell_type": "code",
   "source": [
    "# 显示图片，这里需要把transforms.ToTensor(),进行归一化注释掉，否则是不行的\n",
    "def show_img_content(img):\n",
    "    from PIL import Image\n",
    "\n",
    "    # 打开一个图像文件\n",
    "    # img = Image.open(img)\n",
    "\n",
    "\n",
    "    print(\"图像大小:\", img.size)\n",
    "    print(\"图像模式:\", img.mode)\n",
    "\n",
    "\n",
    "    # 如果图像是单通道的，比如灰度图，你可以这样获取像素值列表：\n",
    "    if img.mode == 'L':\n",
    "        pixel_values = list(img.getdata())\n",
    "        print(pixel_values)\n",
    "show_img_content(img) #这里必须把上面的 transforms.ToTensor(), # 转换为tensor，进行归一化注释掉，否则是不行的"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:08:29.619806Z",
     "start_time": "2025-03-27T08:08:29.609237Z"
    }
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "图像大小: (28, 28)\n",
      "图像模式: L\n",
      "[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 13, 73, 0, 0, 1, 4, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 36, 136, 127, 62, 54, 0, 0, 0, 1, 3, 4, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 102, 204, 176, 134, 144, 123, 23, 0, 0, 0, 0, 12, 10, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 155, 236, 207, 178, 107, 156, 161, 109, 64, 23, 77, 130, 72, 15, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 69, 207, 223, 218, 216, 216, 163, 127, 121, 122, 146, 141, 88, 172, 66, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 200, 232, 232, 233, 229, 223, 223, 215, 213, 164, 127, 123, 196, 229, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 183, 225, 216, 223, 228, 235, 227, 224, 222, 224, 221, 223, 245, 173, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 193, 228, 218, 213, 198, 180, 212, 210, 211, 213, 223, 220, 243, 202, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 3, 0, 12, 219, 220, 212, 218, 192, 169, 227, 208, 218, 224, 212, 226, 197, 209, 52, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 6, 0, 99, 244, 222, 220, 218, 203, 198, 221, 215, 213, 222, 220, 245, 119, 167, 56, 0, 0, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 55, 236, 228, 230, 228, 240, 232, 213, 218, 223, 234, 217, 217, 209, 92, 0, 0, 0, 1, 4, 6, 7, 2, 0, 0, 0, 0, 0, 237, 226, 217, 223, 222, 219, 222, 221, 216, 223, 229, 215, 218, 255, 77, 0, 0, 3, 0, 0, 0, 0, 0, 0, 0, 62, 145, 204, 228, 207, 213, 221, 218, 208, 211, 218, 224, 223, 219, 215, 224, 244, 159, 0, 0, 0, 0, 0, 18, 44, 82, 107, 189, 228, 220, 222, 217, 226, 200, 205, 211, 230, 224, 234, 176, 188, 250, 248, 233, 238, 215, 0, 0, 57, 187, 208, 224, 221, 224, 208, 204, 214, 208, 209, 200, 159, 245, 193, 206, 223, 255, 255, 221, 234, 221, 211, 220, 232, 246, 0, 3, 202, 228, 224, 221, 211, 211, 214, 205, 205, 205, 220, 240, 80, 150, 255, 229, 221, 188, 154, 191, 210, 204, 209, 222, 228, 225, 0, 98, 233, 198, 210, 222, 229, 229, 234, 249, 220, 194, 215, 217, 241, 65, 73, 106, 117, 168, 219, 221, 215, 217, 223, 223, 224, 229, 29, 75, 204, 212, 204, 193, 205, 211, 225, 216, 185, 197, 206, 198, 213, 240, 195, 227, 245, 239, 223, 218, 212, 209, 222, 220, 221, 230, 67, 48, 203, 183, 194, 213, 197, 185, 190, 194, 192, 202, 214, 219, 221, 220, 236, 225, 216, 199, 206, 186, 181, 177, 172, 181, 205, 206, 115, 0, 122, 219, 193, 179, 171, 183, 196, 204, 210, 213, 207, 211, 210, 200, 196, 194, 191, 195, 191, 198, 192, 176, 156, 167, 177, 210, 92, 0, 0, 74, 189, 212, 191, 175, 172, 175, 181, 185, 188, 189, 188, 193, 198, 204, 209, 210, 210, 211, 188, 188, 194, 192, 216, 170, 0, 2, 0, 0, 0, 66, 200, 222, 237, 239, 242, 246, 243, 244, 221, 220, 193, 191, 179, 182, 182, 181, 176, 166, 168, 99, 58, 0, 0, 0, 0, 0, 0, 0, 0, 0, 40, 61, 44, 72, 41, 35, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0]\n"
     ]
    }
   ],
   "execution_count": 12
  },
  {
   "cell_type": "code",
   "source": [
    "#这个代码必须是注释了上面的 transforms.ToTensor()才能够运行的\n",
    "def show_single_image(img_arr):\n",
    "    plt.imshow(img_arr, cmap=\"binary\") # 显示图片\n",
    "    plt.colorbar() # 显示颜色条\n",
    "    plt.show()\n",
    "\n",
    "\n",
    "show_single_image(img)"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T08:09:10.635937Z",
     "start_time": "2025-03-27T08:09:10.362667Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 640x480 with 2 Axes>"
      ],
      "image/png": "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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 13
  },
  {
   "metadata": {},
   "cell_type": "markdown",
   "source": "# 数据准备2，为训练做准备"
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:09:51.331240Z",
     "start_time": "2025-03-27T08:09:51.257271Z"
    }
   },
   "cell_type": "code",
   "source": [
    "from torchvision import datasets\n",
    "from torchvision.transforms import ToTensor\n",
    "from torchvision import transforms\n",
    "\n",
    "mean=0.2860\n",
    "std=0.3205\n",
    "\n",
    "# 定义数据集的变换\n",
    "transform = transforms.Compose([\n",
    "    transforms.ToTensor(), # 转换为tensor，进行归一化\n",
    "    transforms.Normalize(mean, std) # 标准化，mean和std是数据集的均值和方差\n",
    "])\n",
    "# fashion_mnist图像分类数据集，衣服分类，60000张训练图片，10000张测试图片\n",
    "train_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=True,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "test_ds = datasets.FashionMNIST(\n",
    "    root=\"data\",\n",
    "    train=False,\n",
    "    download=True,\n",
    "    transform=transform\n",
    ")\n",
    "\n",
    "# torchvision 数据集里没有提供训练集和验证集的划分\n",
    "# 当然也可以用 torch.utils.data.Dataset 实现人为划分"
   ],
   "outputs": [],
   "execution_count": 14
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:10:26.970821Z",
     "start_time": "2025-03-27T08:10:26.958332Z"
    }
   },
   "cell_type": "code",
   "source": [
    "img_tensor, label = train_ds[0]\n",
    "img_tensor.shape  #img这时是一个tensor，shape=(1, 28, 28)"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Size([1, 28, 28])"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 16
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:10:34.430544Z",
     "start_time": "2025-03-27T08:10:34.392381Z"
    }
   },
   "cell_type": "code",
   "source": "type(img_tensor)",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "torch.Tensor"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 17
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:23:27.001516Z",
     "start_time": "2025-03-27T08:22:44.204136Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#计算均值和方差\n",
    "def cal_mean_std(ds):\n",
    "    mean = 0.\n",
    "    std = 0.\n",
    "    for img, _ in ds:  # 遍历每张图片,img.shape=[1,28,28]\n",
    "        mean += img.mean(dim=(1, 2))  # 计算每张图片的均值，dim=(1, 2)表示计算每张图片的每一个像素的均值,行列共同求均值\n",
    "        std += img.std(dim=(1, 2))\n",
    "    mean /= len(ds)\n",
    "    std /= len(ds)\n",
    "    return mean, std\n",
    "\n",
    "\n",
    "print(cal_mean_std(train_ds))\n"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(tensor([0.0001]), tensor([0.9999]))\n"
     ]
    }
   ],
   "execution_count": 18
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:24:01.818370Z",
     "start_time": "2025-03-27T08:23:58.693840Z"
    }
   },
   "source": [
    "def show_imgs(n_rows, n_cols, train_ds, class_names):\n",
    "    assert n_rows * n_cols < len(train_ds)  #确保打印的图片小于总样本数\n",
    "    plt.figure(figsize = (n_cols * 1.4, n_rows * 1.6))  #宽1.4高1.6，宽，高\n",
    "    for row in range(n_rows):\n",
    "        for col in range(n_cols):\n",
    "            index = n_cols * row + col  # 计算索引，从0开始\n",
    "            plt.subplot(n_rows, n_cols, index+1)#因为从1开始\n",
    "            img_arr, label = train_ds[index]\n",
    "            img_arr = np.transpose(img_arr, (1, 2, 0))  # 通道换到最后一维\n",
    "            plt.imshow(img_arr, cmap=\"binary\",\n",
    "                       interpolation = 'nearest')#interpolation='nearest'是临近插值\n",
    "            plt.axis('off')#去除坐标系\n",
    "            plt.title(class_names[label]) # 显示类别名称\n",
    "    plt.show()\n",
    "    \n",
    "    \n",
    "\n",
    "#已知的图片类别\n",
    "# lables在这个路径https://github.com/zalandoresearch/fashion-mnist\n",
    "class_names = ['T-shirt', 'Trouser', 'Pullover', 'Dress',\n",
    "               'Coat', 'Sandal', 'Shirt', 'Sneaker',\n",
    "               'Bag', 'Ankle boot'] #0-9分别代表的类别\n",
    "#只是打印了前15个样本\n",
    "show_imgs(3, 5, train_ds, class_names)\n"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "<Figure size 700x480 with 15 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAjIAAAGMCAYAAADA5EjBAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAb4tJREFUeJztnQe41FS3hoPSe++9SRekIwqCiDQFRRFFQBRRUcGG/Cr2hogoImDFgvyi0hEFFJCuFKnSm/TeBFGQuc/KvZP7ZZ3sMOdwymTme5/nwJ7Jnkxmt+ysmi4UCoUsQgghhJAAcklaXwAhhBBCSFLhRoYQQgghgYUbGUIIIYQEFm5kCCGEEBJYuJEhhBBCSGDhRoYQQgghgYUbGUIIIYQEFm5kCCGEEBJYuJEhhBBCSGCJqo1M9+7drezZs1+wXtOmTe2/5ELOVa1atWQ7H0ketm/fbqVLl8568803L1j3+eeft+uS6IH9R0jasj1O5uBFb2SGDx9u//j69esnzxXFGa+++qo1ceJEK4hIv0fyN2fOHCuaOH36tD1po+26Uhv2X+zx6aefuvouc+bMVtGiRa2WLVtaQ4cOtU6ePJnWl0gAzsHkIf3FnuDLL7+0Spcubf3666/W5s2brfLlyyfPlcXRRqZjx45W+/btraDxxRdfuF5//vnn1syZMxO8X7ly5RS/lmeeecbq379/xJPwhRdesMvJKdkLGuy/2OXFF1+0ypQpY509e9bat2+ffcPp27ev9dZbb1mTJ0+2atSokdaXSDgHo2Mjs23bNmvhwoXW+PHjrV69etmbmueeey75ro5ENV26dHG9Xrx4sT0J9fupQfr06e0/P86fP2/9888/qXZN0Q77L3Zp1aqVVadOHef1f/7zH2vWrFlW27ZtrRtuuMFat26dlSVLFs/Pnjp1ysqWLVsqXm38wjkYBaol2bjkyZPHatOmjS1VkNd+OroPPvjAKleunJUpUyarbt261pIlSy74HStWrLAKFChg7/r+/PNPY72///7b3kSJREjOX6JECatfv372+5GybNkyq1GjRvYEl6eZkSNHJqhz4MAB6+6777YKFSpki20vv/xy67PPPvNcDB577DH7OuR6LrvsMrsNMNm4tIvUk8+HRYhiJxQvLF261BZ558+f32nzHj16eNa90Njx0u/K6wcffNAel1WrVrU/K30q40mQJ4pwu8vnSeJg/wWLZs2aWQMGDLB27NhhjR492mWXuGXLFqt169ZWjhw5rDvuuMO5ab399tt228taJ2uePLAePXo00ePgq6++smrXrm2fP2fOnFb16tWtd955JxV/fWzCOZgMEhn5cTfddJOVMWNGq3PnztaIESPsxpFG0owZM8bWz8pEkB/9xhtv2J/dunWrlSFDBs/zy7mkk+TJYtKkScYnCJlw8pQxf/58695777XFcKtXr7aGDBlibdy4MSIbFJmcMpFvvfVW+7d8/fXX1v3332//tvDA+Ouvv+wNlajQpHNl0HzzzTf2YnDs2DGrT58+dj3ZrMj1zJ4929701KxZ05o+fbr1xBNPWLt377avSxDx4T333GPVq1fPvm5BBlo8IBvC6667zp4QIs7MnTu3vekV6V5yjJ0w8hQqfSn9JZNdNp4yTqVvO3ToYJ9HoKg9cbD/gsmdd95pPfXUU9aMGTOsnj172u+dO3fOXmcbN25sP2xlzZrVfl/6S2xu7rrrLuvhhx+2JfDDhg2zfvvtN2vBggV230UyDkTCIGtq8+bNrYEDB9rviURIzhFeM0ni4RwEQklk6dKlIloIzZw50359/vz5UPHixUN9+vRx1du2bZtdL1++fKEjR44470+aNMl+f8qUKc573bp1C2XLls0uz58/P5QzZ85QmzZtQmfOnHGds0mTJvZfmC+++CJ0ySWXhObNm+eqN3LkSPs7FixY4Ptb5FxSb/Dgwc57f//9d6hmzZqhggULhv755x/7vbffftuuN3r0aKeeHGvYsGEoe/bsoRMnTtjvTZw40a738ssvu76nY8eOoXTp0oU2b97svCe/V353LNC7d2/7d0fChAkT7LpLliwx1knM2HnuuecSfLe8lnGxdu1a1/sHDx60j8lnyP/D/gs+o0aNumC/5MqVK1SrVi27LGuP1O/fv7+rjqyl8v6XX37pev+HH35wvR/JOJB7gqzl586du8hfF/twDiaNSy5GGiOixmuuucZ+Lbu8Tp062SLEf//9N0F9OSZqqDBXXXWV/b/sCDUiyZAnBNnBy+5SxFl+iFREpDCVKlWyDh065PyJKDV8vgshukHZrYYRSYy8ll2vqJyEadOmWYULF7afLsLIblaeVkTt9fPPPzv1Lr30Uvt9RFRNMja+//57K96Rpwdh6tSptkGiH4kZO5omTZpYVapU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YOFGhhBCCCGBhRsZQgghhASWmN7IbN++3UqXLp315ptvXrDu888/b9clF0f37t2t7NmzX7Be06ZN7b/kQs5VrVq1ZDsfSV0+/fRTe/7JnE3KmCtdunSKXBeJDPZffNwno5U03chI40XyN2fOHCuaOH36tL3xibbrSirDhw+327l+/fppfSmB5NVXX7UmTpxoBY3Vq1dbHTt2tEqVKmVlzpzZKlasmNWiRQvr3XffTetLIxHA/gsO7KuUJb2VhnzxxReu159//rk1c+bMBO9Xrlw5xa/lmWeesfr37x/xRuaFF16wy8kpVUgrvvzyS/uJ6Ndff7U2b95slS9fPq0vKXAbGVmk2rdvbwWFhQsXWtdcc41VsmRJq2fPnlbhwoWtnTt3WosXL7beeecd66GHHkrrSyQ+sP+CA/sqxjcyXbp0cb2WjpWNjH4/NUifPr3958f58+etf/75x4oltm3bZk+08ePHW7169bI3Nc8991xaXxZJYV555RUrV65c1pIlS6zcuXO7jh04cCDNrotEBvsvOLCvLPvhP2vWrCl2/kDbyCxdutRq2bKllT9/fitLlixWmTJlrB49enjW/eCDD6xy5cpZmTJlsurWrWsPqgvZyMjrBx980L65V61a1f7syJEjrQIFCtjHRSoTVn/J54OI/LY8efJYbdq0saUK8tpPh3qhdvRixYoVdpuJ9OrPP/801vv777/tTZRIhOT8JUqUsPr162e/HynLli2zGjVq5IwH6S+NLB533323VahQIVvMe/nll1ufffZZgnqnTp2yHnvsMfs65Houu+wyuw1CoZBTR9pF6snnw2NBdP7RzpYtW+wxrRdWoWDBgk551KhRVrNmzez3pA2qVKlijRgxIsFnRKLXtm1ba/78+Va9evXsdi1btqwtZdWsXbvWPqf0UfHixa2XX37ZfkjQTJo0yR6XRYsWtb9bxt1LL71k/fvvv1a8w/6Lvb4K329ETS32ftJm8rkffvghwed2795t3+tkDcv0f/U++eQTVx156H722Wet2rVr2xupbNmyWVdddZU1e/bsC16zrHH33nuvlTFjRvshN8zo0aPt80nf582b17rtttts6ZKXvaKsxVdffbW9gXnqqaesmJXIXAxyM7ruuuvsG6SohGSQyA0XGz3MmDFjrJMnT9oSBxksb7zxhnXTTTdZW7dutTJkyOD7PbNmzbK+/vpre4DJhkluerIQ3H///VaHDh3s8wg1atSwgohsXOQ3yIDt3Lmz/dtkcyKblORoRzmXbDbr1KljL2wyAbyQhfCGG26wF1KZQKJOFL3ykCFDrI0bN0Zkg3L06FGrdevW1q233mr/Fuk36Sf5beEN7l9//WVPNFGhSZ/KZuebb76xNx/Hjh2z+vTp40xkuR6Z9LLpqVmzpjV9+nTriSeesBcRuS5B1KD33HOPvfjLdQuyYEc7oqtftGiRtWbNGl8jaRkPskhKW4jEcsqUKdYDDzxg91fv3r1ddaVNZTMs7dWtWzd7YZV2lYVPziHs27fPFrOfO3fOnreyuMrm2GtciAGpGI4/+uij9v8yF2VhPnHihDVo0CArnmH/xV5fCbL+yT1M+ihHjhzW0KFDrZtvvtn6448/rHz58tl19u/fbzVo0MDZ+BQoUMD6/vvv7X6Ttu3bt69dT8offfSRvRaKSkvW7o8//thej8WMQNY0L2SjKevl2LFjrQkTJtib0bBkacCAAfb6KmvewYMHbRsf2az89ttvro3a4cOHrVatWtkbHdGwyIYrRQlFEb1795ZH3YjqTpgwwa67ZMkSY51t27bZdfLlyxc6cuSI8/6kSZPs96dMmeK899xzzyX4bnl9ySWXhNauXet6/+DBg/Yx+UyQWbp0qf07Zs6cab8+f/58qHjx4qE+ffokuR27desWypYtm12eP39+KGfOnKE2bdqEzpw54zpnkyZN7L8wX3zxhd3W8+bNc9UbOXKk/R0LFizw/S1yLqk3ePBg572///47VLNmzVDBggVD//zzj/3e22+/bdcbPXq0U0+ONWzYMJQ9e/bQiRMn7PcmTpxo13v55Zdd39OxY8dQunTpQps3b3bek98rvztIzJgxI3TppZfaf/Lb+/XrF5o+fbrTTmFOnz6d4LMtW7YMlS1b1vVeqVKl7PaaO3eu896BAwdCmTJlCj322GPOe3379rXr/fLLL656uXLlst+Xseb33b169QplzZrVNZ6k7eX74wn2X+z1lbRfxowZXWvLypUr7fffffdd57277747VKRIkdChQ4dcn7/tttvsfgi3+7lz5+w1EDl69GioUKFCoR49eiRY3wcNGhQ6e/ZsqFOnTqEsWbLY1xhm+/bt9vW/8sorrvOtXr06lD59etf74bVY1u7UIrCqpfDub+rUqdbZs2d963bq1MlWn4QR8ZogkoQL0aRJE1scG4uINEZ2yvKEJcgOX9rqq6++8hT/JqYdRZIhO//mzZvbTxgi/vRDpCIihalUqZJ16NAh509E2OHzXQh54hRpURiRxMhrkd6JmFOYNm2abWwnTylhRJr08MMP22qvn3/+2al36aWX2u8jomqSNUeegIKMeEzIU6I8qa9cudKWrkl/iTfF5MmTnXr4pH38+HG7T2ROSJ/La0TmSXhMCPKkKOo4HB/SrvI0KRIsrHfHHXckuEb8bnmalO+W84u+ff369VY8w/6Lvb4Srr32WpdEVyT9OXPmdPpA1p5x48ZZ7dq1s8u4VrZs2dLu0+XLl9t1Zf2SNVAQCdyRI0dsSZpIx8N1tCrqlltuse+p0s+i8Qgja7icQ6Qx+J2yllaoUCHB+izr/V133WWlFlG/kZGbi4gzw38izhJkMorITexUROVz44032vpgL3sKsRZHwjdjUUVcCFE9xCKyUZENi2xixOBXxMryJy7YIrr86aefktyOZ86cscWRtWrVstU74cnkx6ZNm2zduyyK+FexYsWIjeJEFy+ibiT8+XB8ix07dtgT75JLLvH0jJPj4f/lfCLe9asXZER9KAuU9J+Imv/zn//YNxxRL/z+++92nQULFtiLq7SrPDxIn4T13fpGqMdHeIzg+Ai3v0ZumBoZD6K+Ff2+LOby3WFHAP3d8Qj7L7b6KpI+kPufqMBFnafXyrv+b+OAa6XY7slmSGyeRDUl9b777jvP9n/ttddsFf63336bwBtX1mfZOEnf6+9dt25dgvVZNmmRrPtxYyMjxpVhV+ewvjFsfCoNLp5OovcV+wXR6w0ePNh+D4Oyyc7UCzTaNGGy6Qg6oq/eu3evvZmRPy9pDe7IE9OOshsXWxWxiRFDNTEivBCy269evbr11ltveR4Xg1uSMsiCIwut/MnGTxZEkZDJTUckaiIlk36RPpC68rQmNkLawPNi5plGFmt5WJEb4Isvvmg/pcpiLE+STz75pKdxabzC/gt+X4U9RS/UB+F2k74VOyYvavyfvaYY5oqNk4SFENs+MSyW88uGRQyQNSLRkfVaJEaykZH+CiPfK/dckUR7XaMOgpra982o38h07drVaty4sbGBRMwpf2KIJMaoIuKUG7MYI6UUsRABWDYqMrDfe++9BMfkyUGMvMTjJykDUtpHzi9SMhFVyuC/ULwdWehE7CoLb1Lbd8+ePbYHEUplxFBYCEcOlY3wqlWr7ImJUpmwqFuOh///8ccf7acmlMroeuHfGyuI2FmQTa48IIiEU8Tf+KQYiZrPhLSbPN1pNmzY4HotwSbFYFDGohgThhHpITHD/gtmX0WKSEBkPRKJukja/Pj2229tzzPpA1yjTOE15D5633332Q+esm7LPSAckkTWZ9lMiYYiLOWOJqJetSQdIR0W/rvyyivt90XUpp8UwlbYiXHXTQphf3h56ggi4rkjg1sGrIg29Z9YwssNXOtvE0PYbU+ePESfK+JUP0T3Kt5AH374oef1ygblQoj+9/3333fpfOW1TH7xvBBEUiQqSrHIx8+J9b08VchTZLieLBbDhg1zfYc8ycqiIBb5YWTjFLSxIDczrydteVoPqwrCT15YT0TSosJNKtKuIjHF8SDicu327/Xd0p8ShZqw/2KtryJF2lVMKsRORrygNAf/z/QiXFfA7/7ll19sex0Tco8VQYBIZu68805HAiTeqXI+0Y7o3yKvZdOalkS9RMaE6P5kUogOVnaLcuOVm6CIMmWypSQipRDDOLkZyu5U/OnFrS4ouX5kgyLtJcZnpp253PxlcRID34tpJzEcE4NdufGLIa2pjWTSiD2NPBHIxJcNq2wkRAIi74vqMPwEY0JsWgYOHGirHqVfpH8kho3ok8Pu4eIiLZsbEbmKAbBIauTJRWwJ3n77bUf6IpsvsR96+umn7fOJ2/2MGTNsdZm4N6JBnmySRHoj4nu5BnlqifZ0DxJNVIwuZf6I6kFuMhIYUdpM2kRE3mIrJRtSaQsxmhZ7NZljIslLzFMkInGBxGX9+uuvt13dw+67YUlZGIkFJLYBIj4Xg2vZPMrnkqLmiEXYf7HVV4nh9ddft9dIWWPErbpKlSq2Ia+o7WQdkrIgD6ryMCnfKzaLIg0TKbvU94vnJaoo2eyKNkTup7Jeynon8YLEtkfWQ6kja6WcUyQ3sq4+/vjjVpoRCqj79fLly0OdO3cOlSxZ0nYRFBfbtm3b2i7FXm5lGu0+bXK/lmvyYuHChaHatWvb7nJBc8Vu165dKHPmzKFTp04Z63Tv3j2UIUMG28UvMe2I7tdh5BxVqlQJFS5cOLRp0yZP92tB3BEHDhwYqlq1qt2nefLksdv4hRdeCB0/ftz3N8m55HPS/+LiKL9PXDqHDRuWoO7+/ftDd911Vyh//vx2/1WvXj00atSoBPVOnjwZeuSRR0JFixa126JChQp2G4ibOrJ+/frQ1VdfbbssSnsEwRX7+++/t10wK1WqZLudSzuUL18+9NBDD9ntE2by5MmhGjVq2O1ZunRpu38++eSTBK620tbiZq/x6udVq1bZ78k5ixUrFnrppZdCH3/8cYJzist9gwYN7HaVPgi7rUq92bNnx437rhfsv9jrK9P9RtpGrynyOalbokQJe22StbV58+ahDz74wKkj69Srr75qf17W01q1aoWmTp2aoL1N6/vw4cPt9x9//HHnvXHjxoUaN25sr/HyJ79JrmPDhg0J1uLUJJ38k3bbKEIIIYSQGLaRIYQQQggxwY0MIYQQQgILNzKEEEIICSzcyBBCCCEksHAjQwghhJDAwo0MIYQQQgJLVATE01FbBwwY4JQlcBAiQXrCPPDAAyl2TZL/Avnoo4+cMkZ1leBoJGXB8OcScRKRYIRhMDeIBOTSScwuFoxUEEtpCQghJMhQIkMIIYSQwMKNDCGEEEICS5pF9pWcOmEkBw+CKd4LFSrkOrZ27VqnLPmAwkiKeqRChQpOOVeuXE45nIfCS3UlOTDCnDhxwlWvSJEinqqw4sWLu+ph0kNJeEkuXlUjuZrC6OSTkvAxjF+yUMyGLlm2w0gOFAQz9Q4ePNh1DDOBSx6oMF5p7QkhhKQOlMgQQgghJLBwI0MIIYSQwMKNDCGEEEICS6rayMyaNcspDxw40Cnny5fPVQ/tU9BeRjhz5oxTPnjwoNGFu3Dhwk65Tp06TnnJkiXG8+XOndtom3PgwAGnnCdPHqd87NgxV72cOXM65QkTJriOETfYt5dcYt5TV6lSxSmfPHnSdQztmjJmzGjsF7SlwT7PkCGDq97Zs2ed8kMPPeQ6NnToUKf8119/edrOEEIISV0okSGEEEJIYOFGhhBCCCGBJVUj+86cOdMply5d2ug2i+J+FPUL+fPnd8rp0///5WsNGbrHosu2VgNkz57dKefIkcMp796921Uva9asnt+l3a9RLTZ//nzXscaNG7texzt+qiVUGf3xxx9OOVu2bEaVEaoXsV+1OnDbtm2e6ijdt4888ojx2v1UYYQQQlIPrsaEEEIICSzcyBBCCCEksKSqamnPnj2e3j1+qiVUEem6qBbQqgRUTSA6CiuqgjDKK6qS9PlRraCvDyPUUrWUEFTdaI80k4cbqoxQ/ed3Dt3/eA4cQ1p1WaNGDc/PCPv27fP0itPXQLUTIYSkHlxxCSGEEBJYuJEhhBBCSGDhRoYQQgghgSVFbWS07QDao2BGaizryKsatGlA+5Q///zT6JaLtjTaJgKvET+jrx0/lzlzZuP1oY3Mxo0bjfXiFWwf7fqMYARmtEfB6MvChg0bPM+tbZwwCjSCtlrCjTfe6JRnzJjhOla7dm3Pa0qjBPKEEEIokSGEEEJIkOFGhhBCCCGBJUVVSxhBVatrMOmeFu9jFFatCsKkgRjZV7vborgfVVVaDYCu3qha0vVQbYHutVqFgejowMTdrtimmtmzZ3u+r1VLLVq0cMpbt241nhtVSzVr1nTKK1ascNXDcXTzzTe7jpUqVSoil35iZvv27a7Xu3btcsoMT0AISQqUyBBCCCEksHAjQwghhJDAkqKqpb1797peZ8qUyVM9o9U4KMLXkXMxsit+TnstocoIvwvf16orTCip1QXoYVOkSBFj9Fe8jnz58hnVGwUKFLDiEexPVA1qUE2EEZcXL17sqpc3b17P8aA94Zo2beqpzujcubOr3quvvnrRajHi5ptvvnHKAwYMcB27/vrrPdWG1apVS9FrGj16tFOuWLGi61i9evVS9LsJIckLJTKEEEIICSzcyBBCCCEksHAjQwghhJDAkqI2MocPH3a9RtuS48ePO+W5c+e66t1xxx1OuWjRoka7G8xijPYtflFjtV0G1kP3a12vYMGCnnYaOtNx5cqVPSMZC+vXr7fi3UbG5Ko8b9481+sDBw542kvoMXX06FFPt30dyRcj8W7evNmzv8iFwRAKOPZ1qIGHH37Y81jZsmVd9VatWuWU7733Xqe8cOHCiK5H28Z98sknTvnQoUOuYxjyAbPZ6zUm1vALJeHH0KFDnfIVV1zhuRbq9RDXNcwkLxQrVsxKTl577TWnXLVqVdexG264IVm/i0Q3lMgQQgghJLBwI0MIIYSQwJKiqiUt3seovBi5VddbtmyZU7766quNomh019SqJBSBo8u1jgCM6iSMAKzdqtElHKP5/vLLL656eI7ixYu7jq1cudIpX3XVVVY8YhJrozusFodjH2mXdlQpmqI063rILbfc4nr96KOPOuW33nrLeO3x6optSpB55MgRYzLP0qVLR6SWwHVAj4drrrnGKU+dOtUpT5gwwag+0nOsW7duqebeHU3oEBamsAc//vij6/Vtt93mqTLSbY7RsXFtHD58uKseqhXr1q3rmYxVq3t1JOiffvrJKe/YscOz3wWqliKfw9jv2EflypUzfi7a1jxKZAghhBASWLiRIYQQQkhg4UaGEEIIIYElXcik9E4BUKf5yCOPeLr5aRdK7daJdjaYNVvbvpjsZfTPRXdgDIW/f/9+Vz10NcWQ69qOAq935MiRxhQN8aqfN7lflylTxpg6AsvYR/qYyeVenx/trPR4GDNmjFMeO3as69ikSZOsWAHnhNZ3J4f+G23bdu7cGVGGa3StX7RokesY2ptdfvnlnnYv2vYFwz1oTDZYXmlMgtafXmEhkHXr1nmuZZi6Q7uoY2gD3T6ZM2f2tL/RdiuYNgT7et++fa56aI+j7XluvfVWz7m6ceNGV73PP//cCjLJYY+yFdK8vPjii542a8LPP//slNu1a+dpL5gSDBs2zCnXrFnTdcxvnfCCEhlCCCGEBBZuZAghhBASWFJVtRQp48ePd8ojRowwiphRlYAqBg2KjrUIFkHXwW3bthlVJLNmzbrALyCRiLxRxYPqAq0KQnWiBsXQKErVUURRDYnuoiVLlnTVW7BggVMuUaKE61gUTpVkUzckNxiWoHnz5sZrQPUF9sWxY8dc9d5//32n3KRJEyte0GMOX2PZpLIVfvjhB9frIUOGOOUHH3zQM9q6VtegOkm72qPqA1W/2bJlc9VD13tUs2/ZssVVD91+dXgEHD/PP/+8U96zZ4+rHt43dBiMtMS0hiRGfYT3urVr1zrlyZMnG6Pgo5pPr6eoxsFI6S1atHDVS0rIEAylIjzwwANOefXq1U65ffv2rnqoNowESmQIIYQQEli4kSGEEEJIYEmfmmI0FHWbIu8K1atX9xQ9axEcnkN7HqC1u59IHT+H50Y1k/a8SIyXDuIn/o1V/Np+xowZxjGAomcUpep+xqSBmERUJwLEqLH4XX/88Yer3oABA4zX2717d6f86aefWtHoxYD1/NoePUW++OIL17Hvv//+otWo9evX9/Q0wXPreYrzWUdiRu8aP9USzj+tKsGxgqJ2rZZADx3tTZHa6DUU+xTbCyMpC5dddplTfuGFF4xeoRjBXHsOdunSJdHXiyrB6dOnu46hShfVwFoFhaolHfUdvUlRjaXXD/TASi7Vkkmtp+ek3/xMigeSXqOeeuopzzFQUqnJ0Tspb968TjlHjhyueqiSwmj5OoIzqosxwrpue0yOrK/9yiuv9IzavGbNGutioESGEEIIIYGFGxlCCCGEBBZuZAghhBASWNLM/dpP549uY+iuJRQqVMgz07S2B0BdOZ5f21iYbFi0OzfqdDFjryaaM4SmFtj22i4I7VgqVKjglAsXLuyqhzp/jNqso/eivhejKmt3PtTvop5d22CdOHHCM+O5X1TKtm3bWilNpPp5v/f79u3rlH/99VdP13TdPg0bNnQd0xmNIwHn0n//+1/XsTlz5njqzLWLKOrdmzVrZnQRRdsI7Es999E2R+v4cVyie3JKEum6gf2GrrI4HnUb6ejH2M633367px2StlU0tV1SQZuI9957z3UM+0Ovw2jPhOsC2jUJDz/8sFNu0KCBFS0hENBO69ChQ0ZbEnRx37Rpk9EOCcNWrAAbJD2vsW91W1177bWe167XWpxbOF51VH20b9TrP9o14f1bR9LH69U2VF5QIkMIIYSQwMKNDCGEEEICS4q6X0eqftCiShQn6mModkQxnXbXRLEVfkaL+kxJzrRYrWLFilYkULXk72b+8ssve7q0o9ufjqprUjNFKnbU14RjQKskcRyhGkwnx5s2bZpRhYHi+uQiUvdOP6pWreqUv/zyS09VilC+fHmjC2b//v2N7p4mcP7pCM6oqsL2RjdNoVatWp4qD50Ar169ep7n0+C8xwSGOgJtWifq1JHNUS2E/dm0aVNXvZkzZxqPzZ8/3ym3bt06ojUOr89PtRnp+oeJgrX7O94btIoR5xquGVpFrMMvJDf6PmJyOdZRkDEkAKpZtEs0qvJ0e1epUsUpz50719MlWpth4JjW65XJPR1d8/XcRfWWXoPxvqyT/KKLPyYRRZWpVrtRtUQIIYSQmIYbGUIIIYQEljRTLfmB3ifaowBVRn5iMP05kyrBpMbyS7jnFzUyaIkFUzs5IUbERdGwjpyMFveoSti8ebOrHnpuoJoBxZt+40GD6kUt7kVPkKR471wMqFLT4loU0fqJ83v27OnpPaRVD88++6zR4wOjteL5dP+hZx96/On5W6NGDadct25dozgZ1UToTbZ06VJXPbwOnXgS1ZU4ZnE+a3VLcpKUpJ16fUEVG6oftHqwWrVqxt93xRVXeB5Db5OkRiX3G384dj788EOnfP311xuTVebPn991DCOu47jX15cSqqXRo0d7qliFHj16eCay1R6BqP7B36ZVYxjRGM+n1VUYebqCGgO4lqH3nb5HmaKj6yj1uNYiBw4cMKqF9LqL37V8+XJPlWlSoESGEEIIIYGFGxlCCCGEBBZuZAghhBASWNLMRsZPl7po0SKjjg1tBVDPrfW7qB/0izSI9VAvryMAYz3UCWodNl5TrGW7NrlW+un+p0yZ4nqNOnm0kcH21S6C6IKp3XdxPOzYscOo38Xvwuv1i1JatmxZ1+uPP/7YSiu2bNlizCqM/eKXQRr18Girol2ssZ4OQ3Dvvfd66up1BFb8XKVKlYwu0WgfsWTJEqdcrFgxywS6sF511VWuY6tWrXLKzZs3N449nN+YKTqptiwphXZLNdkp6MioGCpAR6hGd2ccV35ge2Hkdd0faN+o7Rbxe8eNG2d048fIs9pWCu8HOMa03VhyRB/WtGrVynh+7KdIMzmjDZ5e/7Zt22b8LpxD+Lm/1DlwDcT+01nh8XM49vW9F+c42v7oPsL1w+8+j/dlPX6XLVsWUYR157ovWIMQQgghJErhRoYQQgghgSUqk0ZiokjtroliMFQraDc3VE2giF2re9AdDI+hm58Wk950001OuXPnzq56yZ1cLeigu6h2iUV3Qe2+i/3u55qH0UhRBaXF39gXKNLUfYRiV3RtFH777TfPa4g0iePFgO2zdu1aYxtghFG/ZJCootBumyjW1i7oqL5DN16/xHGY9E6LifF8qA7R4mo8P4q4tes/fq92O0a1JH5OR5ZFdZdOZnoxYETd8ePHu44VKVLEUw2KrqzaLRfniA43gK/1eMTxiutcly5dIlrLtMrIpKrVaklcX/EzWtWB81irLPE1qj60C/Ddd9+d7JGa8Z6i51Zyg79TqzpRtYRtEFLrkClUib4H4jmwnJaR6XEM6DXIC0pkCCGEEBJYuJEhhBBCSGBJVd2HKVmf9hBC8an2RvJLXmYSRfupEvAcpsSCWuSGSQw10eTxkJL4JV5E75MVK1a4jmGUSqynk0ZicjFMYqiTyGF0SLSWb9y4sTHSLI4NLf7G8YWRQ/1IDREsqkfRM0R7D6H4O2/evK56qE7CftBqPVSpYQI8rU5avXq1p6eJFgdjlFWtxkHxN6qWtHcTvsaxp6OeoqeG7r99+/ZFlJRPq5WTC4y2q/sQX2MSS0z8p1VQ2HY6ESCqpHRbotoJfzsmdNWRstErSK/XCJ5PtyuOF+wb3U84n7RqyZQ8Ubdn165dreQG1Um6vfE1jkGtxsH7j189v/UF+xPnzKXqHPoeZuoX031Uv4/nw7IeXzg+/H4XnkOrplEdSNUSIYQQQmIabmQIIYQQEli4kSGEEEJIYElVGxmTLk7rGzFDqHarQz0l2kvoKIQ6sqtJv4vXhJ/Rekn8nM7AjKC9SGq45SY3Jj2o/m1+tkBPPvmkpw5XtwEe0zpudLnGejoKK+rJ0b0Y3Xq1fQK6KGsdLtrMaLuPtATHvW57POYX7Rp1zTjHtOvu77//7nk+PR/RbVvPK5NNi7aFwqi/aOuDtiC6z/B3af082ltoGyG0KcFosnhur0zEyQX+9k6dOkX0Gb2O4W9AN2jdh9jmen3FMY42KHp9wlAJeD6dWRrnJ44DHW0Xz4f1/DIk6/mJYx1tmXSEdd33yY12v05pd2ziDyUyhBBCCAks3MgQQgghJLBEhWpJu3+iKNTP9QxdtnQ9FJmaXDz15zBqsHb5MkWs1O6BKCbVYvloSSKp+wF/A/62SF3JBw0aZHR1btKkievYwoULPdtDu2Ci6BmvT0fs1arHMB999JHxmtAlXIuE8bu0a29agv2i2wrDAWA9nWAQI6ii+sTPzVKD7YOqIB2BFucpqoD1ufF8fq62JtWaHg+4lmg3alRJ4bzXEZyjKYSCXjMw4jGWkyt6LSFBJHpmLCGEEEJIIuFGhhBCCCGBJSqyGmqvgUijk/qpeFA14adawnOgVb22pMfP4fl0wrP8+fM75TTKx3lBtBpOR7c1eUxglNd3333XKQ8ZMsRVr2HDhp7RVIVGjRp5RuXVEXtNagA/sf/kyZOdcrt27VzHpk2b5vkZfT7sM7/Ivn5JT1MaTFqq1TWYoFG3Parhtm7dakzQiONbR8LGNsE5hpGYtccXqmm1qgS9k/Azkap39BjF36jnMKq7/NSahJBgQYkMIYQQQgILNzKEEEIICSzcyBBCCCEksESFjQy6cWpdttbRo00KRifVunK0W0AbAh2BFN1Q0UZGu1/jOfC7tB0C2sgEhW+//dYp33XXXca2QtsJRNsYrF271inXrl3bdWzVqlVOuVy5ck55zZo1rnqmyJ+6vSdMmGC0i4kk0rMGx42OYGoaD2ntVo/2JBj5WEdBjkX8bG4IIfEBJTKEEEIICSzcyBBCCCEksERFZN9t27a5Xmu3SVNCsbJlyxqTx5nUUToRILoe47kxyq92B0a1gnYbRqLV/VpHQ33iiSc8VXmRJs/Tahvsi0WLFrmONWjQwNMFWH8XutFicrwOHTq46rVv3z6iazS5mGvVBKppdILDIPQtIYTEG5TIEEIIISSwcCNDCCGEkMDCjQwhhBBCAktUuF9rOwVMB+Bnq4K2NJgJW9tVoHu3DqWuP2ey+8BrxHQIfuHp/bIIpyUYyl+3T+HChT3bULcJumLr34l2JtqWZMmSJU65ePHiTrlOnTquepi+YPv27U55/Pjxxt+Ftjk4TrzC8F+o/4VChQoZjxFCCIkOKJEhhBBCSGDhRoYQQgghgSUqVEvaNRbVOFr0X7BgQU8VhlYl4OfwfDqb9unTpz3VD1olYlIh6WzaSKQZfFObrl27ul5//fXXTnndunWe7uh+0ZL9XJizZMniOoaf27Jli6e7tY6yPHv2bCsSdBToSFz69WcworCf+zmq2fy+lxBCSMoSnXdaQgghhJAI4EaGEEIIIYElKmTiGzduNKoVtErg6NGjnmWtgjp8+LBTPnHihFPevHmzq97+/fud8ooVK5xyw4YNXfVQzYJqJ1PE2GhGq3t++uknp7xr1y6n/Omnn7rqfffdd55eRX6eP5GiE1JOmzbNKTdt2vSiz1+hQgXP93Gs6WjRVatWNZ4vrRNFEkII+V8okSGEEEJIYOFGhhBCCCGBhRsZQgghhASWdKFUTOOLLqtoYzB48GBXvUOHDnm6W2s36wIFCnieT9izZ49nuXbt2sZosDt27DC6W2fNmtXTlubNN9901UP3br/owLGEtnHCrNZox6TbB+1RTDYsyTG+NHPmzDGOL7w+jHJMCCEkOqFEhhBCCCGBhRsZQgghhASWVFUtEUIIIYQkJ5TIEEIIISSwcCNDCCGEkMDCjQwhhBBCAgs3MoQQQggJLNzIEEIIISSwcCNDCCGEkMDCjQwhhBBCAgs3MoQQQggJLNzIEEIIIcQKKv8DoQxcmQEGm7UAAAAASUVORK5CYII="
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 19
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:24:06.753105Z",
     "start_time": "2025-03-27T08:24:06.744103Z"
    }
   },
   "source": [
    "# 从数据集到dataloader\n",
    "train_loader = torch.utils.data.DataLoader(train_ds, batch_size=32, shuffle=True) #batch_size分批，shuffle洗牌\n",
    "val_loader = torch.utils.data.DataLoader(test_ds, batch_size=32, shuffle=False)"
   ],
   "outputs": [],
   "execution_count": 20
  },
  {
   "cell_type": "markdown",
   "source": [
    "在PyTorch中，`DataLoader`是一个迭代器，它封装了数据的加载和预处理过程，使得在训练机器学习模型时可以方便地批量加载数据。`DataLoader`主要负责以下几个方面：\n",
    "\n",
    "1. **批量加载数据**：`DataLoader`可以将数据集（Dataset）切分为更小的批次（batch），每次迭代提供一小批量数据，而不是单个数据点。这有助于模型学习数据中的统计依赖性，并且可以更高效地利用GPU等硬件的并行计算能力。\n",
    "\n",
    "2. **数据打乱**：默认情况下，`DataLoader`会在每个epoch（训练周期）开始时打乱数据的顺序。这有助于模型训练时避免陷入局部最优解，并且可以提高模型的泛化能力。\n",
    "\n",
    "3. **多线程数据加载**：`DataLoader`支持多线程（通过参数`num_workers`）来并行地加载数据，这可以显著减少训练过程中的等待时间，尤其是在处理大规模数据集时。\n",
    "\n",
    "4. **数据预处理**：`DataLoader`可以与`transforms`结合使用，对加载的数据进行预处理，如归一化、标准化、数据增强等操作。\n",
    "\n",
    "5. **内存管理**：`DataLoader`负责管理数据的内存使用，确保在训练过程中不会耗尽内存资源。\n",
    "\n",
    "6. **易用性**：`DataLoader`提供了一个简单的接口，可以很容易地集成到训练循环中。\n",
    "\n"
   ],
   "metadata": {
    "collapsed": false
   }
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T08:24:11.775899Z",
     "start_time": "2025-03-27T08:24:11.712174Z"
    }
   },
   "cell_type": "code",
   "source": [
    "for datas, labels in train_loader:\n",
    "    print(datas.shape)\n",
    "    print(labels.shape)\n",
    "    break\n",
    "#查看val_loader\n",
    "for datas, labels in val_loader:\n",
    "    print(datas.shape)\n",
    "    print(labels.shape)\n",
    "    break"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([32, 1, 28, 28])\n",
      "torch.Size([32])\n",
      "torch.Size([32, 1, 28, 28])\n",
      "torch.Size([32])\n"
     ]
    }
   ],
   "execution_count": 21
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 定义模型"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:19:03.909938Z",
     "start_time": "2025-03-27T09:19:03.881420Z"
    }
   },
   "source": [
    "class NeuralNetwork(nn.Module):\n",
    "    def __init__(self):\n",
    "        super().__init__() # 继承父类的初始化方法，子类有父类的属性\n",
    "        self.flatten = nn.Flatten()  # 展平层\n",
    "        self.linear_relu_stack = nn.Sequential(\n",
    "            nn.Linear(784, 300),  # in_features=784, out_features=300, 784是输入特征数，300是输出特征数\n",
    "            nn.ReLU(), # 激活函数\n",
    "            nn.Linear(300, 100),#隐藏层神经元数100\n",
    "            nn.ReLU(), # 激活函数\n",
    "            nn.Linear(100, 10),#输出层神经元数10 \n",
    "        )\n",
    "\n",
    "    def forward(self, x): # 前向计算，前向传播\n",
    "        # x.shape [batch size, 1, 28, 28],1是通道数\n",
    "        x = self.flatten(x)  \n",
    "        # print(f'x.shape--{x.shape}')\n",
    "        # 展平后 x.shape [batch size, 784]\n",
    "        logits = self.linear_relu_stack(x)\n",
    "        # logits.shape [batch size, 10]\n",
    "        return logits #没有经过softmax,称为logits\n",
    "    \n",
    "model = NeuralNetwork()"
   ],
   "outputs": [],
   "execution_count": 23
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.707699Z",
     "start_time": "2025-01-16T01:52:58.704733Z"
    }
   },
   "source": [
    "# 看看网络结构\n",
    "model"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "NeuralNetwork(\n",
       "  (flatten): Flatten(start_dim=1, end_dim=-1)\n",
       "  (linear_relu_stack): Sequential(\n",
       "    (0): Linear(in_features=784, out_features=300, bias=True)\n",
       "    (1): ReLU()\n",
       "    (2): Linear(in_features=300, out_features=100, bias=True)\n",
       "    (3): ReLU()\n",
       "    (4): Linear(in_features=100, out_features=10, bias=True)\n",
       "  )\n",
       ")"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 42
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.714907Z",
     "start_time": "2025-01-16T01:52:58.707699Z"
    }
   },
   "cell_type": "code",
   "source": [
    "#为了查看模型运算的tensor尺寸\n",
    "x = torch.randn(32, 1, 28, 28)\n",
    "print(x.shape)\n",
    "logits = model(x)\n",
    "print(logits.shape)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "torch.Size([32, 1, 28, 28])\n",
      "torch.Size([32, 10])\n"
     ]
    }
   ],
   "execution_count": 43
  },
  {
   "cell_type": "code",
   "source": [
    "784*300+300+300*100+100+100*10+10"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.718034Z",
     "start_time": "2025-01-16T01:52:58.714907Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "266610"
      ]
     },
     "execution_count": 44,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 44
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.721534Z",
     "start_time": "2025-01-16T01:52:58.718549Z"
    }
   },
   "source": [
    "for name, param in model.named_parameters(): # 打印模型参数\n",
    "      print(name, param.shape)"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "linear_relu_stack.0.weight torch.Size([300, 784])\n",
      "linear_relu_stack.0.bias torch.Size([300])\n",
      "linear_relu_stack.2.weight torch.Size([100, 300])\n",
      "linear_relu_stack.2.bias torch.Size([100])\n",
      "linear_relu_stack.4.weight torch.Size([10, 100])\n",
      "linear_relu_stack.4.bias torch.Size([10])\n"
     ]
    }
   ],
   "execution_count": 45
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.732732Z",
     "start_time": "2025-01-16T01:52:58.722540Z"
    }
   },
   "source": [
    "# 看看模型参数\n",
    "list(model.parameters())  # 这种方法拿到模型的所有可学习参数,requires_grad=True\n"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Parameter containing:\n",
       " tensor([[ 0.0320,  0.0208, -0.0173,  ...,  0.0018, -0.0004,  0.0193],\n",
       "         [-0.0005, -0.0117,  0.0145,  ...,  0.0256,  0.0004, -0.0234],\n",
       "         [-0.0198,  0.0125,  0.0062,  ..., -0.0054, -0.0275, -0.0185],\n",
       "         ...,\n",
       "         [ 0.0333, -0.0242, -0.0045,  ..., -0.0015, -0.0164, -0.0047],\n",
       "         [ 0.0063, -0.0219, -0.0227,  ..., -0.0056,  0.0288, -0.0321],\n",
       "         [-0.0257,  0.0145,  0.0314,  ...,  0.0152,  0.0298, -0.0304]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([-5.6413e-03, -2.6771e-02,  2.6081e-02,  1.0684e-02, -2.8669e-02,\n",
       "          3.4994e-02, -1.1410e-02, -3.4968e-02, -2.1306e-02, -1.9055e-02,\n",
       "          2.6902e-02,  3.3386e-03,  4.2335e-03,  3.0518e-02, -9.6302e-03,\n",
       "          2.0958e-02,  1.8284e-02,  1.1433e-02, -6.9870e-03, -2.2111e-02,\n",
       "         -1.7430e-02, -2.5515e-02, -3.2894e-02,  2.8200e-02, -1.4747e-02,\n",
       "         -8.5283e-03,  3.3091e-02,  6.6448e-04, -3.1706e-02,  6.6458e-03,\n",
       "         -1.6116e-02,  2.8295e-03, -1.2576e-02,  3.1238e-02,  1.6465e-02,\n",
       "         -7.1913e-04, -1.8849e-02,  5.9420e-03,  1.1223e-02,  1.0648e-02,\n",
       "          1.3682e-02,  1.0255e-02,  1.8183e-02,  1.6112e-02, -1.6621e-02,\n",
       "          8.4616e-03, -3.5115e-03, -2.0977e-02, -1.0412e-03,  1.2032e-02,\n",
       "         -2.8398e-02, -4.7621e-03,  1.5117e-02, -1.0535e-02,  3.0649e-02,\n",
       "         -2.6402e-02, -8.7935e-03,  5.5955e-03, -2.2056e-02, -1.8285e-03,\n",
       "          2.4584e-03,  1.7858e-02,  2.8450e-02,  6.4125e-03, -1.2436e-02,\n",
       "         -2.1858e-02, -2.7960e-02,  1.3508e-03,  9.9240e-03, -2.2632e-02,\n",
       "         -9.3231e-03,  2.1529e-02,  1.2393e-02, -2.8904e-02,  5.9879e-03,\n",
       "         -4.7535e-03,  2.8971e-02, -4.0128e-03, -3.2841e-02,  3.4297e-02,\n",
       "          3.4190e-02,  3.5882e-03,  1.1091e-02, -7.1801e-03,  2.4971e-03,\n",
       "          3.4499e-02,  1.0606e-05, -6.7693e-03, -2.7631e-02, -3.5582e-02,\n",
       "         -1.1289e-02, -2.5544e-02,  3.6777e-03, -4.7284e-03,  1.0049e-02,\n",
       "         -5.9340e-03,  2.7840e-02,  4.9496e-03, -1.2776e-02, -2.5815e-02,\n",
       "          4.9822e-03,  9.4116e-03,  3.2488e-03,  1.4194e-02,  2.1663e-04,\n",
       "         -1.0432e-02, -2.8077e-02, -1.9779e-03,  1.8704e-02,  2.1669e-02,\n",
       "          2.2705e-02, -3.0675e-02,  2.8722e-02, -1.6635e-02,  8.7910e-03,\n",
       "          1.4467e-02, -1.9362e-02, -2.7129e-02,  2.0619e-02, -1.2053e-02,\n",
       "          1.3756e-02, -8.5592e-04, -3.3923e-02,  2.9150e-02,  3.7488e-03,\n",
       "         -1.9585e-02, -9.6158e-03, -2.2185e-03, -3.6099e-03,  1.2292e-02,\n",
       "          2.6792e-02, -2.7938e-02,  4.3739e-03, -1.5515e-02, -1.6755e-02,\n",
       "          1.0568e-02,  3.4447e-02, -3.0722e-02,  3.4094e-02,  1.3680e-02,\n",
       "         -1.9223e-02, -2.3979e-02, -7.1160e-03, -2.9277e-02,  1.9831e-02,\n",
       "          2.4417e-02, -2.4489e-02, -3.1395e-03,  2.6910e-03, -2.3358e-02,\n",
       "          6.7252e-03,  5.5876e-03,  3.2318e-02,  1.1697e-02,  1.7620e-02,\n",
       "          3.1671e-02, -2.9011e-02, -3.2301e-02, -2.3102e-02, -2.0516e-02,\n",
       "          3.0673e-02, -1.0426e-02,  9.6191e-03, -1.0180e-02,  7.7633e-03,\n",
       "         -2.9793e-02,  3.1858e-02,  7.5098e-03, -6.9071e-03,  1.1181e-02,\n",
       "         -3.0611e-02,  2.0116e-02,  2.8349e-02, -1.6633e-02,  1.0013e-02,\n",
       "          1.5181e-02, -8.2144e-03, -2.7198e-02,  2.7459e-03, -2.3268e-02,\n",
       "          2.5118e-02, -3.0523e-02,  7.1630e-03,  1.5876e-02,  8.8550e-03,\n",
       "         -4.4327e-03, -1.8334e-02, -3.5101e-02, -2.1157e-02,  9.5841e-03,\n",
       "          7.4311e-03, -1.4332e-02,  4.0420e-03,  2.9678e-02,  1.7381e-02,\n",
       "          1.2225e-02,  3.2230e-02, -1.6515e-02, -2.2567e-02,  1.0539e-02,\n",
       "         -2.9541e-03,  5.1308e-03,  3.4107e-03, -3.5014e-02, -3.3043e-02,\n",
       "         -2.4658e-02, -1.1967e-02, -1.1901e-02,  2.5946e-03, -2.1511e-02,\n",
       "          3.0033e-02, -1.5178e-02,  1.4358e-02,  1.0154e-02,  1.3055e-02,\n",
       "          2.0735e-03, -2.2925e-02, -2.1103e-02,  2.9311e-02, -2.0840e-02,\n",
       "         -3.1643e-02, -2.4078e-02, -3.9785e-03, -9.1037e-03,  2.1628e-02,\n",
       "          1.4938e-02, -4.0554e-03, -2.5207e-02, -2.1349e-02,  1.5020e-02,\n",
       "         -2.6909e-02,  1.9472e-02,  8.4943e-03, -1.5617e-02,  1.5265e-02,\n",
       "         -9.2094e-03,  2.1890e-02, -3.1737e-03, -8.3552e-03,  1.2900e-02,\n",
       "         -2.2383e-02,  8.9274e-03, -1.7610e-02, -2.9506e-02,  3.3523e-02,\n",
       "          4.6186e-03, -1.1286e-03,  1.0458e-02, -2.7000e-02,  2.0059e-02,\n",
       "          7.5919e-03,  1.9079e-02, -1.0976e-02,  1.3958e-03,  3.0178e-02,\n",
       "         -2.4151e-02,  1.3370e-02, -9.7552e-03,  7.7729e-03,  9.1996e-03,\n",
       "         -8.9093e-03, -2.6997e-02,  3.5015e-02,  1.0289e-03, -2.6442e-03,\n",
       "          2.6590e-02,  1.1670e-02,  2.0156e-02,  1.7969e-02,  1.4160e-02,\n",
       "         -3.2690e-02, -1.0648e-02, -1.8957e-03, -3.3950e-02,  5.4423e-03,\n",
       "          6.2222e-03,  4.6635e-03, -8.8556e-03,  1.9567e-02, -2.4671e-02,\n",
       "         -1.2155e-02, -2.8987e-02, -2.5132e-02,  2.1234e-02, -1.5392e-03,\n",
       "         -1.2539e-02, -2.7963e-02,  1.0049e-02, -1.4169e-02,  2.3886e-02,\n",
       "          1.4374e-02,  2.0175e-02, -3.7146e-03,  7.4707e-03, -1.7503e-02,\n",
       "          4.0547e-03,  1.6996e-02,  1.1798e-02,  5.7526e-03,  2.0881e-02],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([[ 0.0200,  0.0208,  0.0163,  ...,  0.0515,  0.0013, -0.0377],\n",
       "         [ 0.0258, -0.0431,  0.0220,  ..., -0.0002,  0.0352, -0.0460],\n",
       "         [-0.0446, -0.0235,  0.0538,  ..., -0.0491,  0.0051,  0.0362],\n",
       "         ...,\n",
       "         [-0.0163,  0.0495, -0.0281,  ..., -0.0148,  0.0335, -0.0079],\n",
       "         [-0.0514,  0.0180,  0.0123,  ..., -0.0311, -0.0164,  0.0382],\n",
       "         [ 0.0392,  0.0205,  0.0226,  ...,  0.0217,  0.0238,  0.0168]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([ 0.0436, -0.0552, -0.0393,  0.0361, -0.0561,  0.0357,  0.0523, -0.0185,\n",
       "          0.0473,  0.0484,  0.0431, -0.0284, -0.0001,  0.0168, -0.0053, -0.0076,\n",
       "         -0.0328,  0.0157,  0.0489,  0.0550,  0.0353,  0.0220,  0.0301, -0.0308,\n",
       "          0.0523, -0.0511, -0.0492, -0.0473, -0.0569,  0.0293,  0.0108, -0.0183,\n",
       "         -0.0063,  0.0564, -0.0177,  0.0385,  0.0375, -0.0063,  0.0518,  0.0052,\n",
       "          0.0478,  0.0020,  0.0025, -0.0362,  0.0552, -0.0051, -0.0084, -0.0386,\n",
       "         -0.0008, -0.0080,  0.0444, -0.0347,  0.0167,  0.0375, -0.0261,  0.0466,\n",
       "          0.0265, -0.0179, -0.0162, -0.0509,  0.0444, -0.0059,  0.0225,  0.0180,\n",
       "         -0.0179, -0.0009, -0.0269, -0.0065,  0.0575, -0.0113, -0.0215,  0.0425,\n",
       "          0.0375, -0.0193, -0.0416,  0.0512, -0.0054, -0.0233,  0.0248, -0.0557,\n",
       "          0.0303,  0.0237, -0.0298,  0.0126,  0.0479, -0.0438, -0.0212,  0.0496,\n",
       "         -0.0232, -0.0522, -0.0190, -0.0152, -0.0072, -0.0436,  0.0382, -0.0294,\n",
       "          0.0311,  0.0382, -0.0228,  0.0319], requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([[-8.2729e-02, -7.1430e-02,  3.8158e-02,  5.7577e-02, -2.9350e-02,\n",
       "          -9.8039e-02,  3.5158e-02, -4.9063e-03, -6.2413e-03, -7.5141e-02,\n",
       "          -1.3032e-03,  1.0449e-02,  1.9287e-02,  5.7806e-02,  2.2471e-02,\n",
       "           7.1368e-02,  4.6771e-02, -5.6926e-02,  4.2119e-02, -3.7324e-02,\n",
       "           4.1522e-02, -5.6067e-02,  4.0248e-03, -8.6151e-02, -6.3483e-02,\n",
       "          -7.8761e-02,  5.3201e-02,  7.1642e-03, -9.9804e-02, -2.5941e-02,\n",
       "          -2.2549e-02, -9.8039e-02, -2.4141e-02,  2.1820e-02,  8.0868e-02,\n",
       "          -6.9800e-02, -7.1703e-02,  6.9749e-02, -5.4214e-02, -4.8642e-02,\n",
       "          -2.9566e-02,  2.1649e-02,  7.8938e-02, -5.7263e-02, -1.9535e-02,\n",
       "           1.1295e-02, -4.8913e-02, -6.8629e-02,  9.0708e-02,  4.3826e-02,\n",
       "          -1.2557e-02,  8.5529e-02,  2.3347e-02, -3.5502e-02,  4.2203e-02,\n",
       "          -9.9898e-02, -6.7045e-02, -3.5398e-03, -8.6674e-02, -4.4154e-02,\n",
       "          -8.8755e-02, -8.3391e-03, -7.8043e-02, -8.8175e-02, -5.1241e-02,\n",
       "          -7.6819e-02, -4.3424e-02,  3.9788e-02, -8.7487e-02, -4.2416e-02,\n",
       "          -4.4556e-02, -1.3720e-02,  5.2347e-02, -2.3662e-02, -7.1150e-02,\n",
       "          -7.9155e-02,  5.6993e-02, -2.1405e-03,  9.5950e-02, -5.9120e-02,\n",
       "           5.8494e-02, -4.0638e-02, -5.5827e-02,  7.2687e-02,  6.3677e-02,\n",
       "          -8.4774e-02, -4.4774e-02,  3.7323e-02,  5.6813e-02, -7.1304e-02,\n",
       "           2.8150e-02,  7.5655e-02,  6.6477e-03,  9.7420e-02,  3.8415e-02,\n",
       "           2.6964e-02,  9.5397e-02, -6.5526e-02, -3.4421e-02,  4.6275e-02],\n",
       "         [-3.6651e-02,  1.9196e-02,  7.8637e-02,  6.2823e-02,  9.6382e-02,\n",
       "           5.1205e-02,  6.9186e-03, -7.7770e-02,  8.4567e-02,  2.8909e-02,\n",
       "          -4.3141e-02,  1.5069e-02, -3.5485e-02,  8.5920e-02, -3.9946e-02,\n",
       "          -4.8162e-02,  2.5335e-03, -7.3353e-02, -4.2638e-02,  5.1367e-02,\n",
       "          -7.5459e-03,  7.2503e-02, -8.1808e-03, -4.6511e-02,  6.2552e-03,\n",
       "          -3.7845e-02,  8.3515e-02,  6.2397e-02, -1.6098e-02,  3.4811e-02,\n",
       "           8.1032e-02, -4.5470e-02,  9.1390e-02,  9.6533e-02,  8.3842e-02,\n",
       "           2.2644e-02,  6.5110e-02, -7.2416e-02,  2.8822e-02, -8.9522e-02,\n",
       "          -8.4151e-02, -8.5894e-03, -3.8077e-02,  4.9952e-02, -5.2921e-02,\n",
       "          -7.2082e-02, -2.7480e-02, -3.0026e-02,  1.8002e-02,  7.1110e-02,\n",
       "          -5.1728e-02,  6.8480e-03, -3.0540e-02, -2.1803e-02, -7.6609e-02,\n",
       "          -7.1604e-02,  4.6111e-02,  9.1032e-02, -7.8637e-02, -6.4054e-02,\n",
       "          -4.8523e-02, -1.1649e-02,  9.4051e-02, -1.7071e-02,  7.2475e-02,\n",
       "           1.7724e-02, -9.1271e-02,  9.3262e-02, -4.9266e-02,  2.3509e-02,\n",
       "          -1.8667e-02,  2.4435e-02,  3.3204e-02,  6.4734e-02,  1.7500e-02,\n",
       "           3.1586e-02, -2.0185e-02, -3.8431e-02,  7.3408e-02,  4.3467e-02,\n",
       "          -7.1923e-02, -9.9755e-03, -6.0393e-02, -4.7116e-02, -1.2382e-02,\n",
       "          -2.2239e-02,  5.0871e-03, -1.1824e-02,  2.1580e-02, -9.5478e-02,\n",
       "           1.7346e-02,  3.8647e-02,  9.9282e-02, -8.0239e-02, -6.9800e-02,\n",
       "           3.7701e-02,  6.1921e-02,  9.7049e-02, -2.4888e-02,  3.0116e-02],\n",
       "         [-9.7828e-02, -8.4081e-02, -6.5152e-02,  8.8801e-02, -2.0920e-02,\n",
       "          -2.2205e-03,  5.4264e-02,  6.6955e-02,  7.6828e-02,  2.2021e-03,\n",
       "          -3.3903e-02,  3.1582e-02, -4.5211e-02,  1.5277e-02,  5.6525e-02,\n",
       "           6.5152e-02, -3.1654e-03,  7.9041e-02,  8.2808e-02,  7.1784e-02,\n",
       "          -7.8571e-02,  8.4112e-02, -4.1917e-02, -9.8685e-02, -2.1539e-02,\n",
       "          -2.1182e-02, -8.8202e-02, -7.3784e-02, -8.1120e-02,  1.3620e-03,\n",
       "          -5.7194e-02, -8.5909e-02, -4.2216e-02, -3.7053e-02,  9.5912e-02,\n",
       "          -5.4324e-02,  4.9016e-02,  3.3914e-02,  7.3930e-02,  5.1777e-02,\n",
       "          -6.9456e-02, -3.8670e-02,  3.6611e-02, -8.3742e-02, -9.1792e-02,\n",
       "           8.1986e-02,  3.6909e-02, -9.3763e-02,  3.8384e-02, -5.7094e-02,\n",
       "           3.2744e-02, -9.8481e-02,  4.0159e-02,  3.0784e-02, -5.0192e-02,\n",
       "           3.5978e-02, -7.4116e-02,  9.1229e-02, -2.8446e-02,  1.1823e-02,\n",
       "           3.8895e-02,  4.7682e-02,  2.7673e-02, -5.5311e-02, -2.8795e-03,\n",
       "           9.4622e-02,  3.1688e-02, -5.4770e-02,  6.9298e-02, -3.2013e-02,\n",
       "           1.0711e-02, -9.9514e-02,  4.5550e-02,  1.8338e-02,  3.7831e-02,\n",
       "          -2.9380e-02, -4.4191e-02,  3.6940e-02, -1.7611e-02,  3.8758e-02,\n",
       "          -1.4514e-02, -3.9387e-02, -4.0122e-02, -1.8818e-02, -8.8100e-02,\n",
       "          -5.1383e-02, -9.0457e-02, -3.6365e-02, -5.3252e-02,  6.7548e-04,\n",
       "           5.2815e-02,  7.1484e-02,  5.4678e-02, -3.4872e-02,  7.0682e-02,\n",
       "           6.0719e-02, -3.2748e-02,  1.6599e-02, -9.4128e-02, -4.3798e-02],\n",
       "         [-5.2605e-02, -8.5322e-02,  8.4243e-02,  2.3469e-02,  3.2895e-02,\n",
       "          -7.7089e-02, -8.5151e-03, -8.7533e-02,  5.3212e-02, -6.9255e-02,\n",
       "          -9.4208e-02, -7.9329e-02, -5.8584e-02,  2.1689e-02, -4.8092e-02,\n",
       "          -7.1153e-02, -4.8229e-02, -8.8575e-02, -6.9615e-02, -2.7676e-02,\n",
       "          -1.4755e-02,  8.2931e-02, -4.5589e-02, -4.9945e-02, -4.4958e-02,\n",
       "          -9.9045e-02, -4.1149e-02,  7.8451e-02,  8.3748e-02, -5.1191e-02,\n",
       "          -8.3601e-02, -4.4409e-02, -9.8199e-02, -7.0481e-02,  2.5431e-02,\n",
       "           9.5014e-02, -4.8486e-03, -4.2692e-02,  7.4192e-02, -1.4353e-02,\n",
       "          -9.4496e-02, -6.2828e-02,  1.3439e-02, -8.9402e-02,  9.8999e-02,\n",
       "           1.6946e-02,  1.1052e-03, -6.1879e-02, -2.3261e-02, -9.1444e-02,\n",
       "          -7.7663e-02,  1.6478e-02,  2.0330e-02,  5.1384e-04, -3.6762e-02,\n",
       "           8.3187e-02,  1.8664e-03, -1.7260e-02,  1.1386e-02, -1.1758e-02,\n",
       "          -5.5565e-02,  3.4833e-02,  1.5490e-02,  9.3096e-02, -1.3637e-02,\n",
       "          -8.8755e-02,  7.0627e-02,  9.9702e-02,  9.8459e-02, -5.7172e-02,\n",
       "           1.7251e-02,  7.8158e-02,  8.1648e-02,  7.7008e-02, -8.0829e-02,\n",
       "           9.2130e-02, -7.9744e-02,  9.4982e-03, -8.6500e-02, -2.5041e-02,\n",
       "           2.6911e-02, -4.9978e-02,  9.3443e-02, -2.4402e-03, -5.4954e-02,\n",
       "           1.8793e-02, -1.3372e-02, -9.2238e-02,  2.9139e-02, -2.6864e-03,\n",
       "           6.0054e-02, -4.5205e-02,  8.9681e-02, -2.1240e-02,  9.8781e-02,\n",
       "          -7.0968e-02,  5.9850e-02, -5.5783e-02,  3.8985e-02,  7.8580e-02],\n",
       "         [-9.8271e-02,  5.0919e-02, -4.6454e-02,  9.2273e-02, -3.9363e-02,\n",
       "          -7.9465e-02, -1.9197e-02, -8.8537e-02, -4.3146e-03,  3.8220e-02,\n",
       "          -7.5877e-02,  5.6528e-02,  7.6518e-02,  5.2453e-02, -5.3411e-02,\n",
       "           5.6110e-02,  9.0732e-02,  7.9189e-02, -9.7663e-02, -3.8773e-02,\n",
       "          -5.7464e-02, -1.5351e-02, -8.0175e-02,  1.8430e-02,  2.0359e-02,\n",
       "          -7.9627e-02, -5.3094e-02,  6.8355e-03,  1.1426e-02,  9.1715e-02,\n",
       "          -1.7941e-02,  5.1657e-02, -1.9431e-02, -2.3729e-02, -9.4704e-02,\n",
       "          -5.1516e-03, -3.7230e-02, -4.6695e-02, -5.4645e-02,  8.9703e-02,\n",
       "           9.1944e-02,  8.3756e-02,  7.0805e-02,  9.8256e-02, -5.5660e-02,\n",
       "           4.2307e-03, -9.9435e-02, -9.7522e-02, -9.7638e-02,  7.4449e-02,\n",
       "          -3.6996e-02,  3.1527e-02, -2.8971e-02,  2.6016e-02,  7.3362e-02,\n",
       "           5.7434e-03,  1.6528e-02, -2.4879e-02,  6.3373e-03,  5.2746e-02,\n",
       "           3.7653e-02,  9.0316e-02,  7.3742e-02, -6.1623e-02, -1.6866e-02,\n",
       "          -3.7459e-02, -8.5569e-02,  1.6829e-02,  9.5853e-02,  1.0941e-02,\n",
       "           9.7795e-02, -9.8138e-02, -7.5272e-02, -3.0516e-02, -7.1666e-02,\n",
       "          -2.5545e-02, -8.7013e-02, -1.6656e-02, -4.4849e-02,  5.0645e-03,\n",
       "           5.2620e-02,  9.3501e-02, -1.9693e-02,  4.9888e-02, -7.4395e-02,\n",
       "           6.2286e-02,  6.2617e-02,  8.2013e-02, -4.2756e-02, -6.0213e-02,\n",
       "           8.1007e-02, -3.5892e-02,  3.0704e-02,  2.7989e-02,  6.9454e-02,\n",
       "           4.0886e-02,  7.5558e-02, -5.0381e-02, -5.5656e-02, -7.3344e-02],\n",
       "         [ 5.9143e-02, -2.1085e-02, -8.8532e-02,  1.3180e-02, -7.6848e-02,\n",
       "          -5.2856e-02, -7.3069e-02, -6.0228e-02, -7.4378e-02,  1.3118e-02,\n",
       "           5.7951e-02, -8.6772e-02,  6.5471e-02,  6.5349e-03,  1.9902e-02,\n",
       "           4.6503e-03,  3.6212e-02, -2.8308e-02, -4.9671e-03,  5.2268e-02,\n",
       "           1.5343e-02,  1.8472e-02, -6.9837e-02, -6.9558e-02, -7.0699e-02,\n",
       "          -9.1536e-02,  2.4147e-02,  7.9634e-03,  2.5565e-02, -5.9131e-02,\n",
       "          -1.7505e-02,  5.6521e-02,  9.5802e-02,  4.1585e-03, -6.7720e-02,\n",
       "          -2.5287e-02,  1.7363e-02,  7.5970e-02, -5.4998e-03, -9.9004e-02,\n",
       "           8.4714e-02,  9.4766e-02,  8.8542e-02, -4.6117e-02,  9.4526e-02,\n",
       "          -5.5569e-02, -3.6066e-02,  9.0137e-02, -1.4060e-03, -1.5702e-02,\n",
       "           7.2297e-02, -1.1639e-02, -9.0666e-02, -3.3596e-02,  9.8363e-02,\n",
       "           1.4551e-02, -8.4880e-02,  6.5757e-02,  3.8457e-02, -5.9647e-02,\n",
       "           9.6718e-02,  2.8721e-03,  5.8195e-02, -9.0898e-02,  6.5492e-03,\n",
       "          -9.6810e-02,  1.8694e-02,  9.1193e-02,  3.5129e-02, -8.4983e-02,\n",
       "          -8.3941e-03, -9.3676e-02,  7.8527e-02,  5.7590e-02, -4.4594e-02,\n",
       "          -5.4508e-02, -4.7713e-02, -3.8562e-02, -2.9118e-02,  4.7523e-02,\n",
       "           9.7931e-02, -7.9498e-02,  5.4737e-02, -9.6972e-03,  3.5253e-02,\n",
       "          -9.0111e-02, -7.2614e-04,  8.4755e-03,  1.1503e-02,  5.0337e-02,\n",
       "           2.7650e-02,  9.4617e-02,  3.0611e-02, -2.6962e-02, -2.6761e-02,\n",
       "           8.5290e-02, -9.9060e-02, -1.4662e-02, -4.4636e-02,  2.5281e-02],\n",
       "         [ 9.5819e-02, -6.2300e-02, -1.7725e-02,  4.0579e-02, -2.0811e-02,\n",
       "          -7.1370e-02, -4.8164e-02,  6.2584e-02, -5.0754e-02,  4.7701e-02,\n",
       "          -4.5404e-02,  8.6708e-02, -8.2230e-02, -4.5991e-02,  9.0561e-03,\n",
       "           3.8852e-02, -9.1073e-02,  1.2060e-02,  4.9376e-02, -7.8557e-02,\n",
       "           8.8571e-02, -1.3511e-02, -4.9071e-03, -2.7473e-02,  1.5153e-02,\n",
       "          -7.7519e-02,  9.1790e-02, -9.1818e-02,  6.6199e-02,  3.3232e-02,\n",
       "          -3.9976e-02,  9.7829e-02, -2.2462e-02, -1.7184e-02, -9.4861e-03,\n",
       "           8.4068e-02, -7.0055e-02,  5.5698e-02, -7.0032e-02,  2.7748e-02,\n",
       "           7.1142e-02,  2.4155e-02, -7.0095e-02, -9.2605e-02,  9.1698e-02,\n",
       "           2.7217e-02, -9.3420e-02,  7.1181e-02,  1.6731e-02, -5.3137e-02,\n",
       "           7.4431e-02, -7.6068e-02,  1.7849e-02, -7.9575e-02, -7.9065e-02,\n",
       "           9.3641e-02,  3.3072e-02,  6.9243e-02, -1.6191e-02,  5.4337e-02,\n",
       "           1.0485e-02, -3.0141e-02, -6.9337e-02,  5.6193e-02,  7.4765e-02,\n",
       "          -5.4726e-02,  7.7908e-03, -4.7786e-02, -2.2519e-02,  5.6610e-02,\n",
       "           1.9700e-02, -3.1278e-02,  6.4804e-02, -1.8702e-02, -4.0868e-02,\n",
       "           2.7047e-02, -6.6181e-02,  9.7361e-02, -1.7720e-03, -9.3761e-02,\n",
       "          -7.9890e-03,  6.8550e-02,  1.0137e-02,  2.5708e-02,  9.6808e-02,\n",
       "           9.3808e-02,  9.4500e-02,  2.0657e-04,  3.0005e-02,  8.1268e-02,\n",
       "          -1.4889e-02, -8.3217e-02, -9.5621e-02,  8.2752e-02,  8.6464e-02,\n",
       "           9.2946e-02, -2.1682e-02, -1.8833e-02, -5.8452e-02, -2.7767e-02],\n",
       "         [ 6.5493e-02, -2.6960e-02,  2.6696e-02, -4.1003e-02, -3.7277e-02,\n",
       "          -6.7170e-02, -9.9873e-02, -4.1157e-02, -5.0313e-02, -5.7704e-02,\n",
       "           6.3493e-02,  1.1549e-02, -5.5688e-02, -9.8643e-02,  8.0338e-02,\n",
       "          -7.7540e-02,  5.4193e-03,  5.1068e-02, -8.9130e-02,  9.7034e-02,\n",
       "           3.4122e-02, -8.9405e-02,  2.7106e-03,  8.5754e-02, -4.5286e-02,\n",
       "           7.6332e-02,  2.6748e-02,  4.5673e-02,  3.4690e-02, -2.3282e-02,\n",
       "          -1.3285e-02,  9.2744e-02, -9.3384e-02, -1.2962e-02, -8.2401e-02,\n",
       "           2.7265e-02,  5.9938e-02,  1.1489e-02,  2.0887e-03, -2.6772e-02,\n",
       "          -1.8178e-02, -4.4111e-02, -5.4398e-03, -3.4635e-02,  3.9420e-02,\n",
       "           6.8271e-02, -8.6607e-02, -4.4249e-02, -1.8252e-03,  8.4878e-02,\n",
       "          -5.1805e-02, -3.1439e-02,  1.7241e-02, -8.1032e-02, -1.4923e-02,\n",
       "           4.3461e-02,  3.7312e-02, -8.9299e-02, -7.4959e-02,  6.0422e-02,\n",
       "           6.2634e-02, -5.9728e-02,  6.7986e-02,  7.2452e-02, -8.3596e-02,\n",
       "          -7.4613e-03, -4.4128e-02, -8.7481e-02,  2.3922e-02,  6.6272e-02,\n",
       "          -4.6387e-02, -1.4979e-03,  3.3535e-02, -1.2742e-02, -4.6210e-02,\n",
       "          -2.4935e-03, -9.7419e-02, -1.0199e-02,  1.4369e-02,  9.1164e-02,\n",
       "           7.2239e-02, -4.6412e-03,  5.8627e-02, -9.9584e-02,  7.8274e-02,\n",
       "           3.2355e-02,  4.0267e-02,  4.7645e-02, -3.1069e-02, -2.4661e-02,\n",
       "          -4.8689e-02,  2.2899e-03,  3.8359e-02,  4.6776e-02,  5.4396e-02,\n",
       "           2.4363e-02, -2.2024e-02, -7.4441e-02, -1.6534e-02,  9.3097e-02],\n",
       "         [ 6.7325e-02, -6.0875e-02, -3.5223e-02,  7.6622e-04,  4.6816e-02,\n",
       "          -7.2161e-02, -7.5496e-02, -7.6980e-02, -7.7003e-02,  2.4579e-05,\n",
       "           7.8493e-02, -7.3084e-02,  6.0251e-02, -3.2161e-03, -9.0093e-02,\n",
       "           3.2176e-02, -9.2927e-02,  5.2600e-02, -8.5273e-02,  2.9638e-02,\n",
       "           4.0079e-02,  9.4524e-02,  7.4365e-02,  3.3142e-02,  3.8274e-02,\n",
       "          -2.1044e-02,  7.1877e-02,  9.1619e-02,  5.7538e-02,  3.6639e-02,\n",
       "          -9.6582e-02,  6.0750e-02, -3.6285e-02,  7.2966e-02,  6.2856e-02,\n",
       "           3.1169e-02, -4.0406e-02,  7.1640e-02,  8.6744e-02, -3.3519e-02,\n",
       "          -1.7822e-02, -4.5916e-02, -5.1030e-02,  6.7943e-02,  2.9484e-04,\n",
       "           2.3259e-02, -5.2765e-02, -9.8183e-02, -9.3871e-02, -5.2378e-04,\n",
       "           1.2216e-02, -6.2571e-02,  6.8684e-02, -8.5971e-02,  9.6643e-02,\n",
       "          -1.6165e-02,  7.0786e-02, -9.4036e-02,  2.2091e-02,  7.6509e-02,\n",
       "          -5.8176e-03,  1.7614e-02,  7.1431e-02, -2.6882e-02,  6.0613e-02,\n",
       "           4.4436e-02,  3.0100e-02,  9.2525e-02,  6.0518e-03, -1.8634e-02,\n",
       "           1.7868e-02,  2.0820e-02,  6.8925e-02,  7.1846e-02,  1.3843e-02,\n",
       "           8.2396e-03, -9.8680e-02,  2.7906e-02,  5.9917e-02,  8.3603e-02,\n",
       "           2.7895e-02, -5.5254e-02, -1.8064e-02, -1.6769e-02,  5.8769e-02,\n",
       "           4.5227e-02, -9.1809e-02,  8.4751e-03, -9.5915e-02,  3.6566e-02,\n",
       "           6.5433e-02, -4.5852e-02,  5.4611e-02,  1.7872e-02, -6.3608e-02,\n",
       "           4.1673e-02, -7.3351e-02, -1.3065e-02,  6.6492e-03, -8.3550e-02],\n",
       "         [-6.9045e-02,  9.0126e-02, -7.7579e-03,  2.8309e-02, -1.4867e-02,\n",
       "           8.4320e-02, -4.1090e-02,  1.3111e-02, -6.8273e-02,  4.8606e-02,\n",
       "           2.3701e-02, -6.5293e-04, -7.1962e-02,  1.8351e-02,  4.0295e-03,\n",
       "          -6.8009e-02, -8.4055e-02,  8.6088e-02, -5.1754e-02, -1.4431e-02,\n",
       "          -4.2305e-03,  1.0440e-02, -1.2289e-02, -9.9655e-02, -8.4584e-02,\n",
       "           6.1848e-02, -1.7756e-02, -6.4469e-02, -3.7275e-03,  1.2784e-02,\n",
       "           3.7619e-02, -2.8589e-03,  8.6889e-02,  4.3555e-02, -1.2747e-02,\n",
       "          -8.2853e-02, -1.4641e-02, -3.9915e-02, -5.9727e-02,  7.5079e-02,\n",
       "           1.7486e-02, -8.5620e-03,  2.2409e-02, -3.3952e-02,  9.5072e-02,\n",
       "           5.2267e-02, -2.8545e-02,  9.6566e-02,  1.0214e-02, -9.3655e-02,\n",
       "          -4.6204e-02, -8.3114e-02,  7.8232e-02, -4.9240e-02, -3.9953e-02,\n",
       "          -1.9340e-02,  5.7430e-02, -6.6295e-02,  5.3271e-02,  8.6376e-02,\n",
       "          -9.8455e-03, -7.1966e-02, -9.4136e-02,  4.2766e-02, -6.6832e-02,\n",
       "          -5.6390e-02, -8.8340e-02,  9.9504e-02,  5.9372e-02,  3.2552e-02,\n",
       "           7.2083e-02, -4.3490e-02,  4.6783e-02,  9.4423e-02,  5.5038e-02,\n",
       "           1.4364e-02, -5.0857e-02,  3.7978e-02, -6.3343e-02,  1.2677e-02,\n",
       "           5.4542e-02,  2.5872e-02,  1.7183e-02, -5.3739e-02, -5.5935e-02,\n",
       "           1.7180e-02, -5.5586e-02, -5.0573e-02,  7.3850e-02, -1.1172e-02,\n",
       "          -4.5741e-02,  5.1784e-02, -8.3418e-03,  3.5060e-02,  1.9945e-02,\n",
       "           9.6058e-02,  8.1340e-02, -7.3294e-02,  8.7821e-02, -3.0741e-02]],\n",
       "        requires_grad=True),\n",
       " Parameter containing:\n",
       " tensor([-0.0387,  0.0166, -0.0885,  0.0221, -0.0157, -0.0686, -0.0436,  0.0863,\n",
       "          0.0732, -0.0023], requires_grad=True)]"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 46
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.735226Z",
     "start_time": "2025-01-16T01:52:58.732732Z"
    }
   },
   "source": [
    "# model.state_dict()  # 这种方法用于保存模型参数，看能看见参数属于模型的哪一部分"
   ],
   "outputs": [],
   "execution_count": 47
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 训练\n",
    "\n",
    "pytorch的训练需要自行实现，包括\n",
    "1. 定义损失函数\n",
    "2. 定义优化器\n",
    "3. 定义训练步\n",
    "4. 训练"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:19:09.993903Z",
     "start_time": "2025-03-27T09:19:09.936409Z"
    }
   },
   "source": [
    "# 1. 定义损失函数 采用交叉熵损失\n",
    "loss_fct = nn.CrossEntropyLoss() #内部先做softmax，然后计算交叉熵\n",
    "# 2. 定义优化器 采用SGD\n",
    "# Optimizers specified in the torch.optim package,随机梯度下降\n",
    "optimizer = torch.optim.SGD(model.parameters(), lr=0.001, momentum=0.9)"
   ],
   "outputs": [],
   "execution_count": 24
  },
  {
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.740721Z",
     "start_time": "2025-01-16T01:52:58.738484Z"
    }
   },
   "cell_type": "code",
   "source": "10000/32",
   "outputs": [
    {
     "data": {
      "text/plain": [
       "312.5"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 49
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:19:18.378710Z",
     "start_time": "2025-03-27T09:19:16.821022Z"
    }
   },
   "source": [
    "from sklearn.metrics import accuracy_score\n",
    "\n",
    "@torch.no_grad() # 装饰器，禁止反向传播，节省内存\n",
    "def evaluating(model, dataloader, loss_fct):\n",
    "    loss_list = [] # 记录损失\n",
    "    pred_list = [] # 记录预测\n",
    "    label_list = [] # 记录标签\n",
    "    for datas, labels in dataloader:#10000/32=312\n",
    "        datas = datas.to(device) # 转到GPU\n",
    "        labels = labels.to(device) # 转到GPU\n",
    "        # 前向计算\n",
    "        logits = model(datas)\n",
    "        loss = loss_fct(logits, labels)         # 验证集损失,loss尺寸是一个数值\n",
    "        loss_list.append(loss.item()) # 记录损失,item是把tensor转换为数值\n",
    "        \n",
    "        preds = logits.argmax(axis=-1)    # 验证集预测,argmax返回最大值索引\n",
    "        # print(preds)\n",
    "        pred_list.extend(preds.cpu().numpy().tolist())#将PyTorch张量转换为NumPy数组。只有当张量在CPU上时，这个转换才是合法的\n",
    "        # print(preds.cpu().numpy().tolist())\n",
    "        label_list.extend(labels.cpu().numpy().tolist())\n",
    "        \n",
    "    acc = accuracy_score(label_list, pred_list) # 计算准确率\n",
    "    return np.mean(loss_list), acc\n"
   ],
   "outputs": [],
   "execution_count": 25
  },
  {
   "cell_type": "code",
   "source": [
    "1875*20"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-01-16T01:52:58.748562Z",
     "start_time": "2025-01-16T01:52:58.745050Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "37500"
      ]
     },
     "execution_count": 51,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 51
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:40:49.237323Z",
     "start_time": "2025-03-27T09:19:24.692180Z"
    }
   },
   "source": [
    "# 训练\n",
    "def training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=500):\n",
    "    record_dict = {\n",
    "        \"train\": [],\n",
    "        \"val\": []\n",
    "    }\n",
    "    \n",
    "    global_step = 0\n",
    "    model.train()\n",
    "    #tqdm是一个进度条库\n",
    "    with tqdm(total=epoch * len(train_loader)) as pbar: # 进度条 1875*20,60000/32=1875\n",
    "        for epoch_id in range(epoch): # 训练epoch次\n",
    "            # training\n",
    "            for datas, labels in train_loader: #执行次数是60000/32=1875\n",
    "                datas = datas.to(device) #datas尺寸是[batch_size,1,28,28]\n",
    "                labels = labels.to(device) #labels尺寸是[batch_size]\n",
    "                # 梯度清空\n",
    "                optimizer.zero_grad()\n",
    "                # 模型前向计算\n",
    "                logits = model(datas)\n",
    "                # 计算损失\n",
    "                loss = loss_fct(logits, labels)\n",
    "                # 梯度回传，loss.backward()会计算梯度，loss对模型参数求导\n",
    "                loss.backward()\n",
    "                # 调整优化器，包括学习率的变动等,优化器的学习率会随着训练的进行而减小，更新w,b\n",
    "                optimizer.step() #梯度是计算并存储在模型参数的 .grad 属性中，优化器使用这些存储的梯度来更新模型参数\n",
    "\n",
    "                preds = logits.argmax(axis=-1) # 训练集预测\n",
    "                acc = accuracy_score(labels.cpu().numpy(), preds.cpu().numpy())   # 计算准确率，numpy可以\n",
    "                loss = loss.cpu().item() # 损失转到CPU，item()取值,一个数值\n",
    "                # record\n",
    "                # record\n",
    "                \n",
    "                record_dict[\"train\"].append({\n",
    "                    \"loss\": loss, \"acc\": acc, \"step\": global_step\n",
    "                }) # 记录训练集信息，每一步的损失，准确率，步数\n",
    "                \n",
    "                # evaluating\n",
    "                if global_step % eval_step == 0:\n",
    "                    model.eval() # 进入评估模式\n",
    "                    val_loss, val_acc = evaluating(model, val_loader, loss_fct)\n",
    "                    record_dict[\"val\"].append({\n",
    "                        \"loss\": val_loss, \"acc\": val_acc, \"step\": global_step\n",
    "                    })\n",
    "                    model.train() # 进入训练模式\n",
    "\n",
    "                # udate step\n",
    "                global_step += 1 # 全局步数加1\n",
    "                pbar.update(1) # 更新进度条\n",
    "                pbar.set_postfix({\"epoch\": epoch_id}) # 设置进度条显示信息\n",
    "        \n",
    "    return record_dict\n",
    "        \n",
    "\n",
    "epoch = 20 #改为40\n",
    "model = model.to(device)\n",
    "record = training(model, train_loader, val_loader, epoch, loss_fct, optimizer, eval_step=1000)"
   ],
   "outputs": [
    {
     "data": {
      "text/plain": [
       "  0%|          | 0/37500 [00:00<?, ?it/s]"
      ],
      "application/vnd.jupyter.widget-view+json": {
       "version_major": 2,
       "version_minor": 0,
       "model_id": "8f345efe561d4b109ef75d99a716a90d"
      }
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 26
  },
  {
   "cell_type": "code",
   "source": [
    "record[\"train\"][-5:]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T09:40:58.641198Z",
     "start_time": "2025-03-27T09:40:58.615557Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': 0.1694858968257904, 'acc': 0.96875, 'step': 37495},\n",
       " {'loss': 0.14886973798274994, 'acc': 0.90625, 'step': 37496},\n",
       " {'loss': 0.30431580543518066, 'acc': 0.90625, 'step': 37497},\n",
       " {'loss': 0.17817378044128418, 'acc': 0.90625, 'step': 37498},\n",
       " {'loss': 0.2715199887752533, 'acc': 0.9375, 'step': 37499}]"
      ]
     },
     "execution_count": 27,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 27
  },
  {
   "cell_type": "code",
   "source": [
    "record[\"val\"][-5:]"
   ],
   "metadata": {
    "collapsed": false,
    "ExecuteTime": {
     "end_time": "2025-03-27T09:41:09.013052Z",
     "start_time": "2025-03-27T09:41:09.003796Z"
    }
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'loss': np.float64(0.3215956905493721), 'acc': 0.8851, 'step': 33000},\n",
       " {'loss': np.float64(0.3263626162664959), 'acc': 0.8836, 'step': 34000},\n",
       " {'loss': np.float64(0.3258390563983506), 'acc': 0.8853, 'step': 35000},\n",
       " {'loss': np.float64(0.314869149477956), 'acc': 0.8904, 'step': 36000},\n",
       " {'loss': np.float64(0.3271876239357665), 'acc': 0.8864, 'step': 37000}]"
      ]
     },
     "execution_count": 28,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "execution_count": 28
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:41:27.403768Z",
     "start_time": "2025-03-27T09:41:22.904583Z"
    }
   },
   "source": [
    "#画线要注意的是损失是不一定在零到1之间的\n",
    "def plot_learning_curves(record_dict, sample_step=1000):\n",
    "    # build DataFrame\n",
    "    train_df = pd.DataFrame(record_dict[\"train\"]).set_index(\"step\").iloc[::sample_step]\n",
    "    val_df = pd.DataFrame(record_dict[\"val\"]).set_index(\"step\")\n",
    "    last_step = train_df.index[-1] # 最后一步的步数\n",
    "    # print(train_df.columns)\n",
    "    print(train_df['acc'])\n",
    "    print(val_df['acc'])\n",
    "    # plot\n",
    "    fig_num = len(train_df.columns) # 画几张图,分别是损失和准确率\n",
    "    fig, axs = plt.subplots(1, fig_num, figsize=(5 * fig_num, 5))\n",
    "    for idx, item in enumerate(train_df.columns):\n",
    "        # print(train_df[item].values)\n",
    "        axs[idx].plot(train_df.index, train_df[item], label=f\"train_{item}\")\n",
    "        axs[idx].plot(val_df.index, val_df[item], label=f\"val_{item}\")\n",
    "        axs[idx].grid() # 显示网格\n",
    "        axs[idx].legend() # 显示图例\n",
    "        axs[idx].set_xticks(range(0, train_df.index[-1], 5000)) # 设置x轴刻度\n",
    "        axs[idx].set_xticklabels(map(lambda x: f\"{int(x/1000)}k\", range(0, last_step, 5000))) # 设置x轴标签\n",
    "        axs[idx].set_xlabel(\"step\")\n",
    "    \n",
    "    plt.show()\n",
    "\n",
    "plot_learning_curves(record)  #横坐标是 steps"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "step\n",
      "0        0.12500\n",
      "1000     0.78125\n",
      "2000     0.65625\n",
      "3000     0.71875\n",
      "4000     0.78125\n",
      "5000     0.81250\n",
      "6000     0.93750\n",
      "7000     0.87500\n",
      "8000     0.84375\n",
      "9000     0.90625\n",
      "10000    0.90625\n",
      "11000    0.87500\n",
      "12000    0.84375\n",
      "13000    0.87500\n",
      "14000    0.93750\n",
      "15000    0.90625\n",
      "16000    0.81250\n",
      "17000    0.81250\n",
      "18000    0.84375\n",
      "19000    0.87500\n",
      "20000    0.84375\n",
      "21000    0.81250\n",
      "22000    0.93750\n",
      "23000    0.96875\n",
      "24000    0.96875\n",
      "25000    0.84375\n",
      "26000    0.90625\n",
      "27000    0.96875\n",
      "28000    0.84375\n",
      "29000    0.90625\n",
      "30000    0.90625\n",
      "31000    0.93750\n",
      "32000    0.93750\n",
      "33000    0.90625\n",
      "34000    0.96875\n",
      "35000    1.00000\n",
      "36000    0.90625\n",
      "37000    0.90625\n",
      "Name: acc, dtype: float64\n",
      "step\n",
      "0        0.0613\n",
      "1000     0.7969\n",
      "2000     0.8237\n",
      "3000     0.8308\n",
      "4000     0.8431\n",
      "5000     0.8510\n",
      "6000     0.8497\n",
      "7000     0.8591\n",
      "8000     0.8585\n",
      "9000     0.8641\n",
      "10000    0.8622\n",
      "11000    0.8658\n",
      "12000    0.8676\n",
      "13000    0.8697\n",
      "14000    0.8674\n",
      "15000    0.8757\n",
      "16000    0.8717\n",
      "17000    0.8760\n",
      "18000    0.8772\n",
      "19000    0.8749\n",
      "20000    0.8820\n",
      "21000    0.8791\n",
      "22000    0.8774\n",
      "23000    0.8791\n",
      "24000    0.8802\n",
      "25000    0.8836\n",
      "26000    0.8825\n",
      "27000    0.8846\n",
      "28000    0.8864\n",
      "29000    0.8845\n",
      "30000    0.8895\n",
      "31000    0.8818\n",
      "32000    0.8860\n",
      "33000    0.8851\n",
      "34000    0.8836\n",
      "35000    0.8853\n",
      "36000    0.8904\n",
      "37000    0.8864\n",
      "Name: acc, dtype: float64\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "<Figure size 1000x500 with 2 Axes>"
      ],
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAzoAAAHACAYAAABqJx3iAAAAOnRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjEwLjEsIGh0dHBzOi8vbWF0cGxvdGxpYi5vcmcvc2/+5QAAAAlwSFlzAAAPYQAAD2EBqD+naQAAr2xJREFUeJzs3Qd4VGXWB/D/9CQkIYSQhBJ67x0pKihFUKzY17arrgVXZV1Xd+3uir23VT+XdVfsXZAiiAhSpNfQO6TR0jP1e85754YkpEySmcxM5v97nutMJpnMm0lk7plz3nMMHo/HAyIiIiIiokbEGOwFEBERERER+RsDHSIiIiIianQY6BARERERUaPDQIeIiIiIiBodBjpERERERNToMNAhIiIiIqJGh4EOERERERE1Ogx0iIiIiIio0TEjDLjdbhw+fBhxcXEwGAzBXg4RUcSQmdJ5eXlo1aoVjEa+N6bj6xIRUei/NoVFoCMvJmlpacFeBhFRxDpw4ADatGkT7GWEDL4uERGF/mtTWAQ68o6Z/sPEx8fX+v4OhwPz5s3D+PHjYbFYEMq41sAJp/VyrYERTmsNlfXm5uaqE3r932GKvNelcFsv1xo44bRerjUwQmWtvr42hUWgo5cFyItJXV9QYmJi1H3D4Q+Iaw2McFov1xoY4bTWUFsvy7Mi93Up3NbLtQZOOK2Xaw2MUFtrTa9NLLgmIiIiIqJGh4EOERERERE1Ogx0iIiIiIio0QmLPTpEFLrtHZ1OJ8xmM4qLi+FyuRDqtcXhstaGWq/JZFKPwT04RETU2DDQIaI6sdvtOHLkCAoKCpCamqq6T4X6ybIEZuGy1oZcr2wsbdmyJaxWa8Aeg4iIqKEx0CGiOg1L3LNnj8oGyLAuCXpiY2NDfqCkrDs/Pz8s1toQ65VASn532dnZ6vfZpUuXsHheiIiIfMFAh4hqTU6O5SRcethHRUWpfvZyGeonybJmWXs4rLWh1hsdHa1ahO7bt6/0sYiIiBqD0H+lJ6KQFQ7BAtWMv0ciImqM+OpGRERERESNDgMdIiIiIiJqdBjoEBHVUfv27fHyyy/75XstWrRIdVY7ceKEX75fJFm8eDEmT56sGmPIc/j111/79HwPHDgQNpsNnTt3xowZMxpkrURE1HAY6BBRRLngggtw7733+uV7/fbbb7j11lv98r2o7qTFeb9+/fDGG2/49PXSYe7888/HmDFjsG7dOtxzzz24+eabMXfu3ICvlYiIGg67rhERVWi5LMM5ZYhmTVq0aNEga6LqTZw4UR2+evvtt9GhQwe88MIL6uMePXpgyZIleOmllzBhwoQArpSIiBpS4w90di+Cec7fMdARD2BSsFdD1GiDg0K7Myjdu6ItJp+Had50001YunSpOl599VV127///W91++zZs/HQQw9h48aNmDdvnmqdPW3aNCxfvlxlDORkePr06Rg7dmy50jXJBsghZB3vvvsuZs2apbIDrVu3VifTF154YZ1+ti+++AKPPPIIdu/erQZ63nXXXfjzn/9c+vk333xTnZzLQNGmTZvizDPPxOeff64+J5ePP/44du7cqQaCDhgwAN988w2aNGmCSLds2bJyv0chAY7+e6xMSUmJOnTSUl04HA511JZ+n7rcNxjCab1ca+CE03q51sCYv/kI3thiRPfBueiYLOfWweHrc9X4Ax1HEQxZmxAb0zHYKyFqtIodbgx4Zn5QHnvLExMQY/XtnzLZT7N161ZV5vTkk0+q2zZv3qwuH3jgATz//PPo2LEjmjVrpoKHSZMm4Z///Kfax/HBBx+ofSDbtm1D27Ztq3wMCS6effZZPPfcc3jttddw7bXXqhk1iYmJtfq5Vq9ejauuukqt67rrrlMB1x133IHmzZvjxhtvxKpVq/CnP/0J//3vfzFixAgcO3YMv/zyi7rvkSNHcPXVV6t1XHLJJcjLy1Ofk4CUgIyMDKSkpJS7TT6W4KWoqEjNFqpIglz53VYkQbEEknU1f35w/r+JhPVyrYETTuvlWv0nswh4foMJdrcRz3zxKy5q50awFBYW+vR1jT/QMdvUhdEd+lEyEQWWZD2sVqs6MU1NTVW3paenq8snnngC48aNK/1aCUwkINJJYPTVV1/h22+/xdSpU6t8DAlCJMgQTz31lMocrVy5Euedd16t1vriiy/inHPOwV/+8hfEx8eje/fu2LJliwqg5DH279+vsjOy5yguLg7t2rVTWRs90HE6nbj00kvV7aJPnz61enwq78EHH1QZPp0ERZL1Gz9+vPr91OXdSDmpkb85Gdga6sJpvVxr4ITTerlW/yp2uDDlXytgd+erj7PRFJMmDQ/aevSsek0iINDR3pkzeRjoEAVKlMWITY+NC1rpmj8MHjy43Mf5+fl47LHHVBma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EBEREVGjJCfLoR48yBqdTqcqs+Na/Su0CwGJiIiIiIjqgIEOERERERE1Ogx0iIiIiIio0TGH08Cg3NzcOm+ckjZ1cv9QryfkWgMnnNbLtQZGOK01VNar/7vLwXuR+7oUbuvlWgMnnNbLtQZGqKzV19emsAh0pGuGSEtLC/ZSiIgikvw73LRp02AvI2TwdYmIKPRfmwyeMHibToYTHT58GHFxcXXq2S1Rn7wYHThwQA2QCmVca+CE03q51sAIp7WGynrlJUJeSFq1ahXyg+waUiS9LoXbernWwAmn9XKtgREqa/X1tSksMjryA7Rp06be30d+IaH+B6TjWgMnnNbLtQZGOK01FNbLTM7pIvF1KdzWy7UGTjitl2ttvGv15bWJb88REREREVGjw0CHiIiIiIganYgIdGw2Gx599FF1Geq41sAJp/VyrYERTmsNx/VS4/3dhtN6udbACaf1cq2BEU5rDZtmBERERERERLURERkdIiIiIiKKLAx0iIiIiIio0WGgQ0REREREjU5EBToy1O3rr79GOAintVa0d+9etf5169Yh1IXTWsWiRYvUek+cOIFQx7UGRjitlRrXv/fhss7G8O99OK013P5dCpe1hss6Q329jS7QeeONN9C+fXtERUVh2LBhWLlyJULRY489pv4gyh7du3dHKFi8eDEmT56sps1W9sIm/SseeeQRtGzZEtHR0Rg7dix27NgRkmu98cYbT3uezzvvvKCsdfr06RgyZIiapJ6cnIyLL74Y27ZtK/c1xcXFuPPOO9G8eXPExsbisssuQ2ZmZkiudfTo0ac9t7fddhuC4a233kLfvn1LB5gNHz4cP/zwQ8g9r76sNZSeV4qs16ZQfl0SfG0KDL42BUY4vS415temRhXofPLJJ5g2bZpqe7dmzRr069cPEyZMQFZWFkJRr169cOTIkdJjyZIlCAUFBQXquZMX5so8++yzePXVV/H2229jxYoVaNKkiXqe5X/aUFurkBePss/zRx99hGD4+eef1T9qy5cvx/z58+FwODB+/Hj1M+juvfdefPfdd/jss8/U1x8+fBiXXnppSK5V3HLLLeWeW/nbCAaZUP/0009j9erVWLVqFc455xxcdNFF2Lx5c0g9r76sNZSeV4q816ZQfV0SfG0KDL42BUY4vS416tcmTyMydOhQz5133ln6scvl8rRq1cozffp09bH8uF999VXp5x955BFPamqqZ/369Q2+1kcffdTTr1+/Kj8fKmutuA63263W8dxzz5XeduLECY/NZvN89NFH6uM9e/ao+61du1Z97HQ6PTfddJOnW7dunn379jXYWsUNN9zgueiii6q8T7DWKrKystRj//zzz6XPo8Vi8Xz22WelX7N161b1NcuWLVMf//TTT+rj48ePq48LCgo85513nmfEiBGltzXEWsXZZ5/tufvuu6u8T7DWqmvWrJnnvffeC+nnteJaw+F5pcb72hQur0uVrYWvTf7D16bACafXpcby2tRoMjp2u11FoZKq1hmNRvXxsmXLyn2t/Ltz11134YMPPsAvv/yiUnXBICl1SWt37NgR1157Lfbv33/a14TKWnV79uxBRkZGuee5adOmqhSj4vMsSkpKcPnll6s6Y1l/27Ztg1I3Kinubt264fbbb8fRo0cr/bqGXuvJkyfVZWJiorqUv195d6rscytlI7KOyp5bqYMdN24c3G63emcrISGhwdaq+/DDD5GUlITevXvjwQcfRGFhYaX3b8i1ulwufPzxx+odPkm9h/LzWnGtofy8UmS8NoXj65Lga5P/8LUpsl+XGttrkxmNRE5OjvrFpKSklLtdPk5PTy/92Ol04ne/+x3Wrl2rUvKtW7cOwmqh/vGdMWOG+gdO0n+PP/44zjzzTGzatEnVnobSWsuSFxJR2fOsf06Xn5+P888/X/0j/dNPP6kXnYYmpQGSCu7QoQN27dqFv/3tb5g4caL6h8RkMgVtrfI//z333IORI0eqfzCEPH9Wq/W0fxAqe27l4yuvvBJdunTBzJkz1f0acq3immuuQbt27dRJ0YYNG/DXv/5V1Up/+eWXQVnrxo0b1T/IUqYi9c5fffUVevbsqU4OQu15rWqtofi8UuS8NoXr65Lga5N/8LUpcl+XGutrU6MJdHwlNZE2m03Vd0pUGizyD5pO3g2TFxj5A/r000/xhz/8IaTWWldXX321qvlcuHCh2hgaDFdddVXp9T59+qjnulOnTuqdtHPPPTdoa5UaYzl5qGv9u7xTMnToUFX7X/ZFsSHXeuutt5Z7bmUDsDyn8qItz3FDr1VOzuTFQ97h+/zzz3HDDTeouufaCPZa5QUl1J5Xahih8O99JLwuCb42VY2vTZH7utRYX5saTema/IMrT2jFjhXycWpqarlfwKFD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"
     },
     "metadata": {},
     "output_type": "display_data"
    }
   ],
   "execution_count": 29
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## 评估"
   ]
  },
  {
   "cell_type": "code",
   "metadata": {
    "ExecuteTime": {
     "end_time": "2025-03-27T09:41:50.329964Z",
     "start_time": "2025-03-27T09:41:33.418629Z"
    }
   },
   "source": [
    "# dataload for evaluating\n",
    "\n",
    "model.eval() # 进入评估模式\n",
    "loss, acc = evaluating(model, val_loader, loss_fct)\n",
    "print(f\"loss:     {loss:.4f}\\naccuracy: {acc:.4f}\")"
   ],
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "loss:     0.3168\n",
      "accuracy: 0.8898\n"
     ]
    }
   ],
   "execution_count": 30
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.9.7"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
